Closed (fixed)
Project:
Drupal core
Version:
8.0.x-dev
Component:
language system
Priority:
Major
Category:
Task
Assigned:
Unassigned
Reporter:
Created:
13 Jun 2013 at 02:32 UTC
Updated:
29 Jul 2014 at 22:31 UTC
Jump to comment: Most recent file
Comments
Comment #1
Crell commentedSimple option:
public function t($str) {
return $this->translate($str);
}
So the common case becomes:
$this->translate->t();
(We can probably do better, but that's nice and easy. Or just rename the method directly.)
Comment #2
msonnabaum commentedI'd do this. It'll allow for:
Comment #3
Crell commentedI'd be OK with #2 as well.
Comment #4
plachSomehow using
->t()probably would have the advantage of not requiring changes in the code scanning files to find translatable strings.Comment #5
ParisLiakos commentedwell, anyone can name the property however he/she wants, but we should standarize it here. i think calling it
twould make more sense than calling ittranslate, since it is a property. we use verbs for methods.but i would be fine with
translateas wellEdit:
or
would be a good solution too
Comment #6
Crell commentedWith the __invoke() approach we cannot control what the variable is named, that's true. I would prefer a more self-descriptive name, so $this->translate() is better than $this->t() as a convention for core. (That way it reads nicely as an imperative verb.) Contrib modules could do what they want, but I presume most would follow core's lead.
Let's get input from Gabor, too.
Comment #7
ParisLiakos commentedtagging
Comment #8
ParisLiakos commentedand here it is with missing interface, so that we can use the interface for typehints
Comment #9
gábor hojtsyThe coexistence of TranslationInterface and TranslatorInterface sounds tricky :D
Using ->t() would not help with not requiring changes in the string identification code, since this will result in different tokens I think compared to t() the function. (I did not yet check). Anyway, Drupal 8 does all kinds of funky things to not use t() at a lot more places, and people will need to learn a lot more than just "use t", so whatever works best should be used here. I think ->translate() is most descriptive.
Comment #10
ParisLiakos commentedwell it has the
getStringTranslationmethod, so why not be able to use it as translator.Bad news is that __invoke wont work directly on properties..
so, here is an alternative solution based on this
Comment #11
ParisLiakos commentedand you can do this of course
Comment #12
tim.plunkettNice trick, I like that.
Are we also going to change the base of SystemConfigFormBase and ConfirmFormBase?
Comment #13
ParisLiakos commentedi would love too, i guess i should i do it here
Comment #15
ParisLiakos commentedmissed a use statement.
also converted base confirm forms
Comment #17
ParisLiakos commentedrandom failure #2017217: Random failure on UserPasswordResetTest
#15: drupal-translation-dx-2018411-13.patch queued for re-testing.
Comment #18
ParisLiakos commentedreroll
also made setTranslation public
Comment #19
catchBumping this up. I'm seeing loads of patches not injecting the translation service and I'm loathe to commit them still using t() just because the API is so ugly at the moment. Haven't reviewed patches here yet.
Comment #20
gábor hojtsyFrom the point of view of localize.drupal.org, so long as we include text pieces in code (and we do in Drupal 8), we need a reliable way to identify those text pieces. So the #1 requirement from there is that the injected translation service invocations of the translation method need to be identifiable in the same foolproof way that t() is. Eg. the method name should be one that no other object would use. Otherwise we'll end up with false positives, bugos warnings, etc. after parsing.
I'm not sure translate() is such a distinguishable method name for this that can be statically identified unique to this feature. t() has that characteristic by the nature of the function namespace requiring unique function names. Methods between different classes don't ensure that, so we need to be careful which method name we pick. t() may be a method name that would be unlikely to be used for anything else (even if it does sound like very much a Drupalism still). The other extreme is to go very verbose like translateSoftwareText(). Also a format_plural() equivalent would need to be made available.
Finally, this sounds like it will make sweeping API changes, eg. to what services certain controllers need injected, no? It would need to have the approved API change tag if that understanding is right.
Comment #21
tstoecklerCan't the string parser check for "use Drupal\Core\StringTranslation\TranslationBase" and "extends TranslationBase" and then pick up all "$this->translate()"? That sounds pretty foolproof.
Comment #22
gábor hojtsyI'm not sure it is feasible that everything that will need translation injected will be able to extend direct from TranslationBase (as opposed to a service injected into it)?!
Comment #23
tstoecklerYeah, that's true... Hmm...
Comment #24
tim.plunkettI like the __invoke() idea.
In the meantime, #2049709: TranslationManager::translate() should be on an interface needs to happen. I see @ParisLiakos did something like that in #8, but while we determine the perfect solution for this we still need the interface fixed first.
Comment #25
Crell commentedRelated: #2049159: Create a ControllerBase class to stop the boilerplate code madness
Comment #26
dlu commentedMoving to language system per #2050763-16: Refine "base system" component (notes on refactoring of "base system" category here: https://docs.google.com/a/acquia.com/spreadsheet/ccc?key=0AusehVccVSq2dF...).
Comment #27
tim.plunkettSee #2059245: Add a FormBase class containing useful methods for another suggestion similar to ControllerBase
Comment #28
plachIt's a difficult pick but so far we have always categorized interface-translation stuff in the Locale module queue. Architecturally this does not belong to that queue but not even to the language system one, which is about the installed languages and language negotiation.
What about moving this to the Locale module anyway?
Comment #29
berdirControllerBase went in with $this->t(), The not yet committed FormBase is doing the same.
Comment #30
Crell commentedIf we say controllers and forms have a base class that has $this->t(), but services have to use a traditional injected object (or not have translation at all, as we've generally been doing for exceptions), would that be "good enough"? Controllers and forms are the largest users of translatable forms, I suspect. Perhaps we could also have it on BlockBase, but that would round out all of the common cases.
Comment #31
tim.plunkettWe could also ship with a 5.4 trait for $this->t(), at least to make some of contrib happy.
Add Drupal\views\Plugin\views\PluginBase to the list of ones desperately needing this.
Comment #32
gábor hojtsySounds like $this->t() is the way to go. Patch needs update.
Comment #33
gábor hojtsySome places use ->translate() while others use ->t(). This will not end well... Can we get on the same ground?!
Comment #34
tim.plunkettEverything using ->translate() is wrong, thankfully there are only four classes.
I'm adding protected function t() to EntityListController, since we'll need it on all of those (copying from FormBase)
Unfortunately, neither StaticLocalActionDeriver nor AggregatorCategoryBlock have a base class, and DerivativeBase is in Drupal\Component anyway. Many derivatives will need translation, we might want to consider a Drupal\Core DerivativeBase, and have a protected function t() on there.
Basically, we really need traits :(
EDIT: Oh, I didn't even realize there was a preexisting patch, sorry. This is completely from scratch
Comment #35
ParisLiakos commentedinstead of adding everywhere t(), (set|get)TranslationManager methods, why dont we stick with the TranslationBase in #18, and make everything (including formBase and controllerBase) extend it?
Comment #36
gábor hojtsyOk, it is good we have a decision here. I reopened #2019679-3: Support for Drupal 8 $this->t() then for potx, so we can figure out localize.drupal.org support before it is too late :D
Comment #37
tim.plunkett@ParisLiakos So that is why traits are needed. Because we're going to make
class FormBase extends DependencySerializationin #2004282: Injected dependencies and serialization hell .It can't extend from both.
Comment #39
ParisLiakos commenteda ha, yeah i didnt think about this scenario..i guess then #34 is the best we can do till we require 5.4
Comment #40
ParisLiakos commentedComment #41
tim.plunkettA few fixes.
Comment #42
gábor hojtsyI think ATM its of paramount importance to spread the availability of the t() method in base classes, so new code being written will use this as best practice. Figuring out better inheritance based solutions later once inheritance trees are reworked may be an option, but IMHO this is a blocker to apply the t() method properly everywhere. So let's do this ASAP.
Comment #43
webchickWell that definitely looks much nicer.
Also enjoy seeing all the - signs in these classes.
Not moving down from RTBC, bit...
My biggest concern is that we're starting to see these docs copy/pasted now to 4+ places in core. None of them are remotely as detailed as https://api.drupal.org/api/drupal/includes!bootstrap.inc/function/t/7, explaining the use of @ and ! and % placeholders, when to use it, when not to use it, etc. I'm not sure how people using this method are supposed to learn of them and view proper examples on how they work.
Would it be better to instead move this to a single interface that we could selectively implement on e.g. FormBase, ControllerBase, BlockBase, etc? This would allow us to centralize the work of creating and maintaining these docs and the function signature, logic, etc. so if we needed to make changes to it in the future, we'd do so once and it would propogate everywhere.
Comment #44
berdirInterfaces can only be added for public methods. This is about protected helper methods, so that doesn't work, we don't want them to be public.
Maybe we could agree on some kind of short-form, with a @see t()? I'd suggest to do that as a follow-up for all t() methods, though.
Comment #45
tim.plunkettYes, I didn't want to be the one to propose we skimp on docs and just say
@see t()(or@see \Drupal\Core\StringTranslation\TranslationInterface::translate()).But maybe that is better than having half-ass docs in 4+ places (and yes, there will be more places this will end up).
Comment #46
ParisLiakos commentedyes, just having
everywhere is much better, cause in the long run it will be more maintainable, than keeping/updating same docs everywhere...
Comment #47
webchickCool, we are in agreement.
Then since the point of this issue is to introduce these protected t() helper methods, doesn't it make sense to tackle this here?
Comment #48
tim.plunkettSold.
Comment #49
jhodgdonInstead of just a @see WhateverItIs90, could we have a sentence explaining why, something like "See the WhateverItIs::method() documentation for a detailed explanation of placeholders blah blah blah"?
Comment #50
tim.plunkettAfter further discussion with @jhodgdon, we settled on this.
Comment #51
webchickWorks for me.
Committed and pushed to 8.x. Thanks!
Comment #52
ParisLiakos commentedDo we need a change notice here saying that
$this->translationManager->translate()*won't* work, and $this->t() or t() should be used, else strings wont be picked up for translation?Comment #53
webchickGood call. Yes!
Comment #54
ParisLiakos commentedi wrote https://drupal.org/node/2079611 it could use a review though ;)
Comment #55
berdirMade some small adjustments (used
instead of <?php for the example at the bottom, works imho better inline in a sentence and clarified what doesn't work.Comment #56
ParisLiakos commented#2079797: Provide a trait for $this->t() and $this->formatPlural()
Comment #58
jhedstromFollow-up added #2120059: Cleanup temporary t() functions in phpunit tests.