Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Form translation and its inconsistencies #208

Open
mabar opened this issue Jan 22, 2019 · 5 comments
Open

Form translation and its inconsistencies #208

mabar opened this issue Jan 22, 2019 · 5 comments
Milestone

Comments

@mabar
Copy link
Contributor

mabar commented Jan 22, 2019

As @fprochazka firstly mentioned in #34, current api for form translations is inconsistent and not enough. For example:

  • getLabel() does not accept translation parameters (I have usecase with 3 identical inputs for which makes sense to add their number as parameter)
  • addRule() error message accepts only int parameter (see Validator::formatMessage)
  • $caption and addError() have no way to pass parameters

It would be absolutely ok to be unable to pass parameters in some cases, like getLabel() or errors. I would simply disable control translator. But they are translated by form translator instead of control translator, so translator cannot be used in whole form.
So I was forced to disable translator for whole form. But I have another form at the same page with translator enabled. And both of these forms use default error messages, which are contained in Validator::$messages. Static variable, shared between all forms. Form without translator displays form.rule.equal as placeholders are used instead of natural language. Well, I cannot use translator for both forms as replacing messages for form without translator would cause fail in form with translator (translators usually throw exception when message without translation is given)

Also, these inconsistencies cause many wtf moments for new nette/forms users. I know a huge part of nette code and I still have these moments when I don't know if something will be translated or not.
Imagine you are user without knowledge of internals. You set translator into form. Will be your select element label, prompt and values translated? What if you disable only control translator? Each of them acts differently, headache.

It's getting much more complicated to find out under which conditions translator is used. So ability to pass parameters for translator everywhere would not really solve the problem.
Could we at least mention in docs that prefered way how to translate forms is not built-in translator and copy validator messages into a non-static instance so it could be overwritten for individual forms?
With non-statical Validator instance could be default messages translated with a simple function and keep behavior for rest forms (which may use translator) same to keep it backward compatible.

@Kocicak
Copy link

Kocicak commented May 3, 2019

+1 for this. Especially for getLabel. I need \Nette\Utils\Html for checkbox label and it gets translated by Form's translator, not control translator. Other values are translated by BaseControl::translate() method. Why label isn't?

I suggest calling $this->translate() method id BaseControl::getLabel() method.

@Kocicak
Copy link

Kocicak commented May 3, 2019

OK, after some thinking - i get it why it is translated by Form's translator. Can we just make an exceptin for \Nette\Utils\Html? Something like Translate method has? !($v instanceof Html) ?

@mabar
Copy link
Contributor Author

mabar commented May 3, 2019

Imho custom rendering should be done in template, to be compliant with MVC. If you want it anyway, create new issue as it is out-of-scope.

I solved problem with translator simply -> don't use translator in forms at all. My current solution needs all forms to be created through factory to translate default messages properly (and without overhead during container initialization). See FormFactory

@Kocicak
Copy link

Kocicak commented May 3, 2019

Yeah, I can solve it by disabling translator for that form and every other thing (elements, validator messages etc) put into $translator->translate(...). But it's not as convenient as just excluding Html class from translating. No one wants to translate html.

Edit: custom rendering is just as bad solution as the one described. The thing I need is to create a checkbox: "I aggree with GDPR" and that "GDPR" abbr is actually a link to another page. It's as simple as that. Can't do it with translator in form.

@dg dg added this to the v4.0 milestone Apr 20, 2020
@Ciki
Copy link
Contributor

Ciki commented Feb 6, 2021

can somebody tell me why in https://github.com/nette/forms/blob/master/src/Forms/Controls/BaseControl.php#L277 is used
$translator = $this->getForm()->getTranslator();

instead of

$translator = $this->getTranslator();

?

This way even if I disable control's translator, the label still gets translated (twice in my use case).
See code

$lblAmount = $this->translate('Suma v %s s DPH', $this->activeStorage->currency);
$form->addText('amount', $lblAmount)
	->setTranslator(null)

I wanted to create PR for this but then came across this issue. Why do we need to use form's translator in control's getLabel()?

Thanks

Edit probably related to 6271110, so now I get it, but I am leaving it here for future me or sb like me :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants