Problem/Motivation
There's many places in core where t() function is used in classes without dependency injection.
It makes this classes hard to unit test because t() defined in core/includes/bootstrap.inc
Also it makes harder to get rid of this include in later core
The sniff is already enabled for Plugins, in phpcs.xml.dist
<rule ref="DrupalPractice.Objects.GlobalFunction">
<include-pattern>*/Plugin/*</include-pattern>
</rule>
Proposed resolution
Replace usage with one of following ways
- $this->t() for controllers using StringTranslationTrait or add if it's missing
- new TranslatableMarkup() in static methods
Remaining tasks
Final issue to enable the sniff and fix any remaining problems.
#3507043: Enable DrupalPractice.Objects.GlobalFunction
Cleanup
#3133726: [meta] Remove usage of t() in tests not testing translation
User interface changes
API changes
no
Data model changes
no
Release notes snippet
n/a
Comments
Comment #2
prabha1997 commentedI am working on this issue
Comment #3
prabha1997 commentedComment #4
alexpottI disagree with the scoping here. The scope here should be to replace t() with $this->t() where that is available. For all of core. Breaking this up into a module by module feels like it will create a lot busywork for reviewers and committers. Let's roll all the sub issues up into this one. And then we can worry about the rest of the calls to t() from classes where we need to consider dependency inject etc.
Comment #5
alexpottWe also need to make a decision about whether we should only use the StringTranslationTrait or extend from ControllerBase. I'm not sure but I think we need the answer before we progress on all the issues here.
Comment #6
xjmNote that replacing the same things on a per-module basis is explicitly disallowed by our scope guidelines. https://www.drupal.org/core/scope explains considerations for scoping these large changes.
If the patch would be too large or complicated as one thing here, we should group the replacements by concept instead. In this case, this would be the pattern of usage: Is the trait already available? Which base class is extended? Etc.
See https://www.drupal.org/core/scope#fix-scope for how to fix the scope of these sub-issues. Please mark them as duplicates and transfer issue credits for them over here. The usages should be audited for the presence or absence of the string trait instead.
Comment #7
andypostuse the StringTranslationTrait or extend from ControllerBaseThat's the blocker, because it affects maintenance
- Extending from base classes bounds to constructors inheritance
- Using trait for
t()looks more efficient for contrib- OTOH
new TranslatableMarkup(...)is the most straight-forward instead of "magic T"From the last point following a question about usage in tests - @alexpott mentioned some issue about test config form which could be great example to copy/paste
but we got agreement to not use t() in tests (separate clean-up)
EDIT #3109743-14: t() calls should be avoided , use $this->t() instead in Config module
Comment #8
alexpott@andypost controllerbase has no constructor.
Comment #9
alexpottSo I think we need
Comment #10
alexpottHere's a patch that enables the sniff. The end goal has to be to commit a patch containing this sniff so we know that we'll not introduce anymore in core.
Comment #11
alexpottNote I think we'll need to address t() in tests to order to do this. Or maybe we need to update the rule to have an option to ignore tests.
Comment #12
cilefen commentedJust FYI there are a number of sub-issues that don't list this as a parent.
Comment #13
andypostQuick numbers of usage
t(- 295 in
*Form.php- 45 in
*Controller.phpComment #14
swatichouhan012 commentedI tried to cover all t calls() in form and controller here wrt scope, kindly review.
https://www.drupal.org/project/drupal/issues/3116874
Comment #15
xjmThanks @swatichouhan012, that's a better approach than per module. I think we should split it a bit more though. As I said on that issue:
A fourth category is just simply removing
t()calls from tests, as per: https://www.drupal.org/docs/8/testing/phpunit-in-drupal-8/phpunit-browse...I've closed most of the per-module children as duplicates. Let's get consensus on the parent here before proceeding with the rest of the children.
Comment #16
andypostThen goes plugins and services
Also while it happening some places could use
new TranslatableMarkup()instead of traitComment #17
andypostCan't find the issue about usage in tests - policy, it was about providing testing modules with t() property used to make copy/paste less buggy
Another related here is #1532612: Move Examples Project into Drupal core
Comment #18
xjmComment #19
joseph.olstadPlease forgive me for thinking out loud and having an opinion on this, I know that all of you are working very hard on core and doing a lot of great work. However I've noticed a lot of convenient drupalisms disappear since Drupal 7 and this initiative has started to 'leak' into contrib and I'm looking for the rationale behind this initiative because t() is extremely widespread in it's usage. My inner child cries at the thought of thousands of modules going through yet another sort of a 'purist' cleansing initiative, I would like to follow the links to the rationale for pushing this into contrib?
Costs related to disrupting contrib with t(); "cleansing":
touching thousands of modules of code, subject to human error and also to custom code outside of contrib.
None of us are machines, we are humans and creatures of habit. Microsoft of all companies understood this since the 1970s when they introduced BASIC and made variants for all the computer platforms. Simple BASIC programs could work on several platforms, this was why Microsoft was propelled into billions and billions of dollars in revenues. Later in 2001 even their MFC (microsoft foundation classes API) has gone through relatively slow evolutionary changes, except once when they introduced major disruptions in 2001 and 2002 shifting to the .NET framework but they did make a very good effort to attempt to minimize the API changes and make the transition as smooth as possible.
frameworks like Django have promised API stability and forward compatibility(lmgtfy). Why is this important?
So far I have only heard promises of removing deprecated apis, how about promises to only deprecate when absolutely necessary?. (and rationale based on actual performance profiling tests to prove that there is a performance gain and that the gains are greater than the costs)?
I'd rather see real solutions, what is the actual problem that we trying to solve here other than to create disruption and introduce new human errors and disrupt contrib?
If we remove all the drupalisms in Drupal then maybe eventually it becomes something other than Drupal?
Comment #20
dww@all Re:
t()in tests. Now tracked in this child issue: #3133726: [meta] Remove usage of t() in tests not testing translation@joseph.olstad re: #19: Yes, it's a big undertaking. Yes, it's error prone. But it's not just for the sake of making busy work and inconveniencing module maintainers. Please read the first 3 sentences of this issue summary:
Are those reasons enough for all the work and effort that will be required? I'm not sure. Is this "technical debt" more expensive to the project as a whole than the vast hordes of known bugs that are languishing in the queue for years (most of which are already fixed, but haven't been committed since we require tests for every bug fix)? Almost certainly not. Will Drupal promise to "only deprecate when absolutely necessary"? No way. What can you do about it? Put your energies where you think they should go, and hope that they are well received. That's all any of us can do. /shrug
Comment #22
quietone commentedClosed #2471467: Phase out global t() in classes using StringTranslationTrait as a duplicate.
Comment #23
andypostOne more done #3122912: t() calls should be avoided , use $this->t() instead in Form Builders
Comment #24
longwaveClosed a number of child issues as duplicate because they were scoped by module, and that approach was already rejected by core committers.
Comment #25
mradcliffeMost of the forms in form_test module use
t()directly rather than$this->t().Comment #30
quietone commentedGather the issue working to fix t() in one place, tag for Coding standards, update the IS and move to the 'other' component.
Comment #31
quietone commentedComment #32
jonathan1055 commentedAdding parent because this is fixing a DrupalPractice rule
Comment #34
quietone commentedComment #35
quietone commentedComment #36
quietone commentedComment #37
quietone commentedComment #38
quietone commentedTwo more completed, #3497408: Fix DrupalPractice.Objects.GlobalFunction in modules and #3497410: Fix DrupalPractice.Objects.GlobalFunction in hooks.
Comment #39
quietone commentedYay! All the child issues are fixed.
And related to this I made a Coding Standards to discuss making it a standard the t() is only used in tests for testing translations. #3508485: Discuss t() in tests