Description
Is your feature request related to a problem? Please describe.
Due to the change in \Nette\Localization\ITranslator
, where string
return type was added in version 3
, we're no longer able to have easily translatable pieces of HTML in our Latte templates/Nette forms.
Explain your intentions.
Previously, in Nette 2.4, we were able to return instances of \Nette\Utils\Html
(class which implements the \Nette\Utils\IHtmlString
interface) from our own implementation of \Nette\Localization\ITranslator
. This is no longer possible as of version 3
, due to the added string
return type, which disallows the previously working logic.
This, unfortunately, makes the transition to Nette 3 very painful.
A "translatable piece of HTML" can, for example, be some piece of Markdown rendered into HTML. Markdown-markuped text is identified by our translator, processed, and then returned as a \Nette\Utils\Html
object (instead of just string
) - which is then not escaped when placed inside a Latte template.
Minimal example from our current 2.4
translator:
class OurTranslator implements \Nette\Localization\ITranslator {
private $parsedown;
// ...
public function translate($message, $count = null) {
$translated = gettext($message);
return $this->processMarkdown(sprintf($translated, ...func_get_args()));
}
/**
* If the string begins with a magic "md:" prefix, process that string as
* if it uses markdown markup. This is opt-in to avoid any potential
* vulnerabilities from strings provided by untrusted third-parties.
*
* @return string|\Nette\Utils\Html
*/
protected function processMarkdown(string $message) {
if (strpos($message, "md:") === 0) {
$html = new \Nette\Utils\Html;
return $html->setHtml($this->parsedown->line(substr($message, 3)));
}
return $message;
}
}
The translator can simply return a Html
object and then we don't have to deal with manually escaping/unescaping everything in Latte templates. This is because the \Latte\Runtime\Filters\escapeHtmlText
itself supports this:
public static function escapeHtmlText($s): string
{
return $s instanceof HtmlStringable || $s instanceof \Nette\Utils\IHtmlString
? $s->__toString(true)
: htmlspecialchars((string) $s, ENT_NOQUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
Now, because of the change of the ITranslator
interface forcing the string
return type, this mechanism can no longer be used.
Yes, in PHP 8 with union types it might be ok to use union string|IHtmlString|HtmlStringable
return type for the translate
method, but since that's not what can be done now, I'm proposing for the removal of the currently needlessly limiting string
return type.
Activity
her-ur commentedon Nov 16, 2021
We are in the same situation as @smuuf
dg commentedon Nov 16, 2021
How about this?
her-ur commentedon Nov 16, 2021
Looks good 👍
Translator: changed interface, accepts and returns string|Stringable [C…
dg commentedon Nov 16, 2021
I think it's not even a BC break.
Translator: changed interface, accepts and returns string|Stringable [C…
Translator: changed interface, accepts and returns string|Stringable [C…
Translator: changed interface, accepts and returns string|Stringable [C…
Translator: changed interface, accepts and returns string|Stringable [C…
Translator: changed interface, accepts and returns string|Stringable [C…
Translator: changed interface, accepts and returns string|Stringable [C…
Translator: changed interface, accepts and returns string|Stringable [C…
Translator: changed interface, accepts and returns string|Stringable [C…
Translator: changed interface, accepts and returns string|Stringable [C…
61 remaining items