In various places the concrete class LanguageManager is type hinted. Use the LanguageManagerInterface instead.

In the ControllerBase and FinishResponseSubscriber classes (maybe others?) declare the $languageManager property to have class \Drupal\Core\Language\LanguageManagerInterface and refer to it as a "language manager object" instead of a "LanguageManager object" in the doc block.

Review each @see comment in doc blocks that refers to the \Drupal\Core\Language\LanguageManager class (or one of its methods) and decide whether it should refer instead to \Drupal\Core\Language\LanguageManagerInterface.

Update use Drupal\Core\Language\LanguageManager; directives, as appropriate, to refer to the interface.

Contributor tasks needed
Task Novice task? Contributor instructions Complete?
Create a patch Instructions Yes
Reroll the patch if it no longer applies. Novice Instructions Yes
Update the issue summary Instructions Yes
Review patch to ensure that it fixes the issue, stays within scope, is properly documented, and follows coding standards Novice Instructions
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

znerol’s picture

Status: Active » Needs review
FileSize
26.43 KB
sun’s picture

Status: Needs review » Reviewed & tested by the community

Nice clean-up! :)

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

Missing:

  • \Drupal\Core\Controller\ControllerBase
  • \Drupal\aggregator\Plugin\AggregatorPluginManager
  • \Drupal\custom_block\CustomBlockFormController
  • \Drupal\block\Plugin\Type\BlockManager
  • \Drupal\ckeditor\CKEditorPluginManager
  • \Drupal\ckeditor\Plugin\Editor\CKEditor
  • \Drupal\editor\Plugin\EditorManager
  • \Drupal\field\FieldInfo
  • \Drupal\field\Plugin\views\field\Field
  • \Drupal\filter\FilterPluginManager
  • \Drupal\image\ImageEffectManager
  • \Drupal\locale\Form\TranslateFormBase
  • \Drupal\migrate\MigraterPluginManager
  • \Drupal\search\SearchPluginManager
  • \Drupal\tour\TipPluginManager
  • \Drupal\user\Form\UserPasswordForm
  • \Drupal\views\Plugin\ViewsPluginManager
  • \Drupal\views\Tests\ViewsDataTest
  • \Drupal\Tests\Core\Datetime\DateTest
  • \Drupal\Tests\Core\Entity\EntityManagerTest (this can be changed to mock on the interface)
znerol’s picture

Issue tags: +Novice
icseh.’s picture

Assigned: Unassigned » icseh.
icseh.’s picture

Assigned: icseh. » Unassigned
Status: Needs work » Needs review
FileSize
32.25 KB
52.14 KB

This is the new patch. I hope I didn't forget any file.

LinL’s picture

Status: Needs review » Needs work
Issue tags: +Needs reroll

Patch no longer applies, tagging for reroll.

visabhishek’s picture

Status: Needs work » Needs review
FileSize
32.24 KB

Simply reroll...

YesCT’s picture

YesCT’s picture

Issue tags: +D8MI
YesCT’s picture

just re-rolled. (no interdiff)

conflicted with #2170775: Remove array typehint from $plugin_definition.

took out the array type hint, but kept the manager interface type hint this issue wanted.

review coming.

YesCT’s picture

not sure of the best way to review this.

So far I'm doing:
ag LanguageManager core | grep -v LanguageManagerInterface

and then looking at all the results there.

YesCT’s picture

looks like the interdiff in #6 had some changes, like archive manager and condition manager, but those changes are not in the *patch* in #6

So I'm going to go through the interdiff in 6. patch coming.

[edit:]

woah! the interdiff in 6 reverted some of the changes to typehint on the manager. I dont understand why that might have been done.

YesCT’s picture

ok. I went through and did more.

In this interdiff, I did *not* remove any un-used uses. (but my previous re-roll did carry one over)
I also did not add any unrelated coding style changes.
--------
should any of these also be changed?

ag LanguageManager core | grep -v LanguageManagerInterface
core/core.services.yml:264:    class: Drupal\Core\Language\LanguageManager
core/core.services.yml:278:      - [initLanguageManager]
core/includes/bootstrap.inc:1896: * @see \Drupal\Core\Language\LanguageManager
core/includes/bootstrap.inc:1936: * @see \Drupal\Core\Language\LanguageManager::getLanguage()
core/includes/bootstrap.inc:1951: * @see \Drupal\Core\Language\LanguageManager::getLanguage()
core/includes/install.core.inc:17:use Drupal\Core\Language\LanguageManager;
core/includes/install.core.inc:323:    ->register('language_manager', 'Drupal\Core\Language\LanguageManager')
core/includes/install.core.inc:1415:    $standard_languages = LanguageManager::getStandardLanguageList();
core/includes/install.core.inc:1463:  $standard_languages = LanguageManager::getStandardLanguageList();
core/includes/install.core.inc:1843:  $standard_languages = LanguageManager::getStandardLanguageList();
core/includes/install.core.inc:2120:  $languages = LanguageManager::getStandardLanguageList();
core/lib/Drupal/Core/Entity/EntityManagerInterface.php:257:   * @see \Drupal\Core\Language\LanguageManager::getFallbackCandidates()
core/lib/Drupal/Core/Language/Language.php:104:      $predefined = LanguageManager::getStandardLanguageList();
core/lib/Drupal/Core/Language/LanguageManager.php:5: * Contains \Drupal\Core\Language\LanguageManager.
core/lib/Drupal/Core/Language/LanguageManager.php:340:   * @see \Drupal\language\ConfigurableLanguageManager::setConfigOverrideLanguage()
core/lib/Drupal/Core/StringTranslation/TranslationManager.php:73:  public function initLanguageManager() {
core/modules/language/language.admin.inc:9:use Drupal\Core\Language\LanguageManager;
core/modules/language/language.admin.inc:17:  $predefined = LanguageManager::getStandardLanguageList();
core/modules/language/language.module:10:use Drupal\language\ConfigurableLanguageManager;
core/modules/language/language.module:467:    ConfigurableLanguageManager::rebuildServices();
core/modules/language/language.module:499:      ConfigurableLanguageManager::rebuildServices();
core/modules/language/language.services.yml:9:      - [initLanguageManager]
core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php:5: * Contains \Drupal\language\ConfigurableLanguageManager.
core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php:15:use Drupal\Core\Language\LanguageManager;
core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php:20: * Overrides default LanguageManager to provide configured languages.
core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php:102:   * Constructs a new ConfigurableLanguageManager object.
core/modules/language/lib/Drupal/language/LanguageNegotiator.php:104:  public function initLanguageManager() {
core/modules/language/lib/Drupal/language/LanguageNegotiator.php:236:      $instance->setLanguageManager($this->languageManager);
core/modules/language/lib/Drupal/language/LanguageServiceProvider.php:52:    $definition->setClass('Drupal\language\ConfigurableLanguageManager')
core/modules/language/lib/Drupal/language/Tests/LanguageListModuleInstallTest.php:44:    $this->assertEqual(\Drupal::state()->get('language_test.language_count_preinstall', 0), 1, 'Using LanguageManager::getLanguages() returns 1 language during Language installation.');
core/modules/language/lib/Drupal/language/Tests/LanguageNegotiationInfoTest.php:50:   * @return \Drupal\language\ConfigurableLanguageManager
core/modules/language/tests/Drupal/language/Tests/LanguageNegotiationUrlTest.php:93:    $method->setLanguageManager($this->languageManager);
core/modules/simpletest/lib/Drupal/simpletest/TestBase.php:1074:    $this->container->register('language_manager', 'Drupal\Core\Language\LanguageManager')
core/tests/Drupal/Tests/Core/DrupalTest.php:311:  public function testLanguageManager() {
core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php:114:    $this->languageManager = $this->getMockBuilder('Drupal\Core\Language\LanguageManager')
core/tests/Drupal/Tests/Core/PathProcessor/PathProcessorTest.php:89:    $method_instance->setLanguageManager($language_manager);
core/tests/Drupal/Tests/Core/PathProcessor/PathProcessorTest.php:139:    $method->setLanguageManager($this->languageManager);
core/tests/Drupal/Tests/Core/Utility/TokenUnitTest.php:64:    $this->languageManager = $this->getMockBuilder('\Drupal\Core\Language\LanguageManager')
sun’s picture

Property names + class method names should be left alone.

Only type-hints and @var should be changed.

Each @see reference requires individual review to verify whether the preceding comment talks about the general interface or the default implementation. If it talks about aspects of the default implementation, then the @see is to be left alone. Otherwise, it should refer to the interface.

Mixologic’s picture

Patch applied to latest HEAD, and a PHPStorm search no longer shows any instances of LanguageManager typehinted in any constructors (and the @var/use statements were updated accordingly.

I am seeing some things that seem like they might need some work:

both Drupal\Tests\Core\Utility\TokenUnitTest and Drupal\Tests\Core\Entity\EntityManagerTest
use getMockBuilder, when they can use the getMock() pattern (which all other tests use)

$this->languageManager = $this->getMockBuilder('\Drupal\Core\Language\LanguageManager')
      ->disableOriginalConstructor()
      ->getMock();

I switched those to:

$this->languageManager = $this->getMock('Drupal\Core\Language\LanguageManagerInterface');

to match everything else.

+++ b/core/lib/Drupal/Core/TypedData/TranslatableInterface.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\TypedData;
 
-use Drupal\Core\Language\LanguageManager;
+use Drupal\Core\Language\LanguageManagerInterface;
 
 /**
  * Interface for translatable data.

I dont think we intend to change any use statements inside of Interfaces. That being said, I dont think we need this particular use statement at all. Should probably open another issue to remove it. I set that back to its original state in this patch.

As far as the other instances that YesCT has above:
EntityManagerInterface.php - this @see only takes us to an @inheritdoc if it is left as is. It points it at the interface in the patch.
EntityManagerTest.php -- see above
TokenUnitTest.php -- see above

core.services.yml - Should be a class - no change needed.
bootstrap.inc - all three instances are in deprecated functions, no change needed.
install.core.inc - Im not sure if we expect to have any other LanguageManager interface objects during install. So these probably do not change. The others are static calls. no change needed.
LanguageManager.php - the real mccoy. no change needed.
TestBase.php - has a @todo about removing once this class has no calls to t() and format_plural() - so its probably not intended to work with an interface.

The following were static class methods that are not on the interface and shouldnt change:

  • language.admin.inc
  • LanguageListModuleInstallTest.php
  • Language.php

The following were examples of grep overreach returning instances of ConfigurableLanguageManagerInterface or functions like initLanguageManager

  • TranslationManager.php
  • language.module
  • language.services.yml
  • ConfigurableLanguageManager.php
  • LanguageNegotiator.php
  • LanguageServiceProvider.php
  • LanguageNegotiationInfoTest.php
  • LanguageNegotiationUrlTest.php
  • DrupalTest.php
  • PathProcessorTest.php
YesCT’s picture

+++ b/core/tests/Drupal/Tests/Core/Utility/TokenUnitTest.php
@@ -61,9 +61,7 @@ public static function getInfo() {
-    $this->languageManager = $this->getMockBuilder('\Drupal\Core\Language\LanguageManager')
-      ->disableOriginalConstructor()
-      ->getMock();
+    $this->languageManager = $this->getMock('Drupal\Core\Language\LanguageManagerInterface');

huh.
so we dont need to do this disable and getMock when we use the interface for the mockbuilder?
seems reasonable.

Mixologic’s picture

Thats what I assumed when I found 19 other tests that followed that pattern. But looking at the difference between getMock and getMockBuilder reveals that the latter is just a fluent interface for the former. What the test results reveal is that the 'disableOriginalConstructor()' calls have no apparent affect on the tests. Thats not to say that the tests are the same. So maybe those shouldnt be made to look like the others.

znerol’s picture

Re #18, #19. It is always preferable to generate a mock based on an interface. This is because there will be no side-effects due to code called on the original class (interfaces do not contain any code). The disableOriginalConstructor() method is in fact a workaround necessary to make some classes mockable in the first place.

As a consequence when switching from mocking a class to mocking an interface, in many cases it is also possible to eliminate the fluent getMockBuilder() and instead use the simpler (and shorter) getMock() method.

alexpott’s picture

+++ b/core/modules/language/tests/language_test/lib/Drupal/language_test/Controller/LanguageTestController.php
@@ -8,7 +8,7 @@
-use Drupal\Core\Language\LanguageManager;
+use Drupal\Core\Language\LanguageManagerInterface;

@@ -28,7 +28,7 @@ class LanguageTestController implements ContainerInjectionInterface {
-   * @var \Drupal\Core\Language\LanguageManager
+   * @var \Drupal\Core\Language\LanguageManagerInterface

@@ -38,7 +38,7 @@ class LanguageTestController implements ContainerInjectionInterface {
-  public function __construct(HttpKernelInterface $httpKernel, LanguageManager $language_manager) {
+  public function __construct(HttpKernelInterface $httpKernel, LanguageManagerInterface $language_manager) {

+++ b/core/modules/locale/lib/Drupal/locale/Form/TranslateFormBase.php
@@ -9,7 +9,7 @@
-use Drupal\Core\Language\LanguageManager;
+use Drupal\Core\Language\LanguageManagerInterface;

@@ -38,7 +38,7 @@
-   * @var \Drupal\Core\Language\LanguageManager
+   * @var \Drupal\Core\Language\LanguageManagerInterface

@@ -56,10 +56,10 @@
-   * @param \Drupal\Core\Language\LanguageManager $language_manager
+   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
...
-  public function __construct(StringStorageInterface $locale_storage, StateInterface $state, LanguageManager $language_manager) {
+  public function __construct(StringStorageInterface $locale_storage, StateInterface $state, LanguageManagerInterface $language_manager) {

ConfigurableLanguageManagerInterface? i think all of these depend on functionality in the ConfigurableLanguageManager that comes with the language module.

Mixologic’s picture

@alexpott: are you suggesting that we us ConfigurableLanguageManagerInterface instead of LanguageManagerInterface in those instances?

If so, can we tackle that refactoring in a follow up issue? This issue is targeted at getting concrete classes out of constructors and replacing their dependencies with interfaces.

YesCT’s picture

I made a separate issue for that. It could use some clarification, or just a preliminary patch changing one and seeing what happens.

#2271553: Some things should be typehinted with ConfigurableLanguageManagerInterface not LanguageManagerInterface

--
I'm going to reroll this now.

YesCT’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
FileSize
59.75 KB

the only kinda interesting conflict was #2039435: Convert EntityManager to extend DefaultPluginManager which removed some lines this patch was changing in EntityManager.php

just a straight reroll.

Next step is to see if there are new places to make this same kind of change.

Mixologic’s picture

Next step is to see if there are new places to make this same kind of change.

@YesCT: I had searched the codebase for other examples of constructors taking in concrete classes that have interfaces, created patches and issues - see all the other related issues on this.

There may still be other concrete classes for which there wasnt an interface, but could use one, and in a couple of cases there were concrete classes that had an interface, but the code was relying on functionality provided by the class that wasnt covered in the interface.

So theres probably still some cleanup that can take place in adding methods to interfaces, as well as creating new interfaces.

Mixologic’s picture

Also if you're a phpstorm user, a global search using the following regex reveals everywhere that a concrete class is being used as a parameter (mostly):

@param \\Drupal\\.*(?<!Interface) \$.*

Its a lot of noise, and theres a lot of instance where I cant forsee there being much value in having the ability to swap out another implementation of some of these concrete classes (ImageToolkitManager? probably not)

@param \\Drupal\\Core\\.*(?<!Interface) \$.*
benjifisher’s picture

Issue summary: View changes

Update for DrupalCon Austin sprint: I do not think that a novice can mark this RTBC, but I think that a beginner could help a lot to summarize the changes in this patch. It would help a lot to read Comment #15 below, then review every change in the proposed patch and make a list of any changes that need further review. I am skeptical of the change to ControllerBase.php. There are places where "LanguageManager object" in comments is replaced by "language manager object": it would be good to list them, in case we decide that this should be removed or made a separate patch.

I will ask the testpbot to review the patch; it might need another re-roll.

benjifisher’s picture

Status: Needs review » Needs work

The last submitted patch, 24: 2212427-type-hint-use-interface-instead-of-class-24.patch, failed testing.

benjifisher’s picture

Issue summary: View changes
Issue tags: +Needs reroll
mgriego’s picture

Assigned: Unassigned » mgriego

Working on the reroll.

mgriego’s picture

Status: Needs work » Needs review
FileSize
57.07 KB

OK, here's a rerolled patch:

  1. Updated to PSR-4
  2. The FieldInfo class (and, hence, FieldInfo.php file) no longer exists, so its reference was removed from the patch

This is a simple re-roll of #24 (other than the FieldInfo removal).

mgriego’s picture

I discovered one more instance of LanguageManager being used instead of the interface in the ActionManager class. New patch that includes that update. My search for *just* the LangagueManger was:

@param \\Drupal\\Core\\Language\\LanguageManager(?<!Interface) \$.*

That's what turned up this new instance. I didn't see any other instances of params, though there are places where "use \Drupal\Core\Language\LanguageManager;" exists in the code...

mgriego’s picture

I've searched through the code, and I'm not seeing any other instances of type-hinting the concrete LanguageManager class, so I *think* the updated patch in #33 is good to go.

mgriego’s picture

Assigned: mgriego » Unassigned

I guess this needs to be picked up by someone else for review and committing, so un-assigning myself.

mgriego’s picture

Issue tags: -Needs reroll
Berdir’s picture

Status: Needs review » Needs work
Issue tags: +Needs reroll

#2281905: Stop caching plugin discovery/info hooks by language removed a huge amount of LanguageManager type hints, this will need a re-roll which will conflict for all of those, but it will make the patch a lot smaller.

Mixologic’s picture

Status: Needs work » Needs review
FileSize
24.94 KB

Merge conflicts in 28 files.

Since I did a *lot* of merging, theres a good change I hit a >> when I meant to hit an X and vice versa. Please review thoroughly. As @berdir said, its a much smaller patch now.

Berdir’s picture

Status: Needs review » Needs work
Issue tags: -Needs reroll

Found two unused LanguageManager use in AliasManager.php and Drupal\Core\TypedData\TranslatableInterface

benjifisher’s picture

The last time I looked at this patch, I was bothered by the fact that it does several different things: it changes type hints (which is all that it should do according to the issue summary), it changes wording in doc blocks, and more. (See my comment #27 above.)

IMHO, this issue should do just what it says, in which case the "Quick fix" and "Novice" tags are appropriate. Other changes included in the current patch may be done in separate issues. Given the comments in #37 and #38, now looks like a good time to start from scratch rather than re-rolling again.

If you disagree, and want to do everything that the current patch does, then please

  1. Remove the "Quick fix" and "Novice" tags
  2. Update the issue summary to say what the patch does
Mixologic’s picture

Typically the motivation to split patches is based on whether or not they can be committed separately, and independently of each other. I don't believe that we would want to commit the type hint changes without also updating the docblocks to reflect that change, or update the test cases to work, as they are all interdependent changes.

So, this patch really only does one thing - it replaces concrete class type hints with interface type hints wherever possible, which is now in a dramatically reduced number of places.

I've updated the patch to reflect @berdirs findings as well.

Berdir’s picture

Status: Needs review » Reviewed & tested by the community

Agreed, those changes make sense to do here.

benjifisher’s picture

Issue summary: View changes
Issue tags: -Quick fix, -Novice

Neither of these changes looks to me like changing a type hint. As I said in #27, I am skeptical of these changes, but I admit that I have only looked at the patch, not at the change in context, so maybe I am missing something:

--- a/core/lib/Drupal/Core/Controller/ControllerBase.php
+++ b/core/lib/Drupal/Core/Controller/ControllerBase.php
@@ -51,7 +51,7 @@
   /**
    * The language manager.
    *
-   * @var \Drupal\Core\Language\LanguageManager
+   * @var \Drupal\Core\Language\LanguageManagerInterface
    */
   protected $languageManager;
 
@@ -273,7 +273,7 @@ protected function currentUser() {
   /**
    * Returns the language manager service.
    *
-   * @return \Drupal\Core\Language\LanguageManager
+   * @return \Drupal\Core\Language\LanguageManagerInterface
    *   The language manager.
    */
   protected function languageManager() {

As @sun said in #15, each @see reference has to be reviewed individually:

--- a/core/lib/Drupal/Core/Entity/EntityManagerInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityManagerInterface.php
@@ -274,7 +274,7 @@ public function getExtraFields($entity_type_id, $bundle);
    * @return \Drupal\Core\Entity\EntityInterface
    *   An entity object for the translated data.
    *
-   * @see \Drupal\Core\Language\LanguageManager::getFallbackCandidates()
+   * @see \Drupal\Core\Language\LanguageManagerInterface::getFallbackCandidates()
    */
   public function getTranslationFromContext(EntityInterface $entity, $langcode = NULL, $context = array());

The first change here is what I meant by changing wording in doc blocks; is this related to the change in type hinting? The second change looks wrong to me.

 class FinishResponseSubscriber implements EventSubscriberInterface {
 
   /**
-   * The LanguageManager object for retrieving the correct language code.
+   * The language manager object for retrieving the correct language code.
    *
-   * @var LanguageManager
+   * @var \Drupal\Core\Language\LanguageManagerInterface
    */
   protected $languageManager;

This is the sort of change described in the issue summary. Of course, when you change the type hint, you should update the @var line in the doc block; this is not the sort of change I was objecting to.

@@ -40,12 +40,12 @@ class FinishResponseSubscriber implements EventSubscriberInterface {
   /**
    * Constructs a FinishResponseSubscriber object.
    *
-   * @param LanguageManager $language_manager
-   *  The LanguageManager object for retrieving the correct language code.
+   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
+   *   The language manager object for retrieving the correct language code.
    * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
    *   A config factory for retrieving required config objects.
    */
-  public function __construct(LanguageManager $language_manager, ConfigFactoryInterface $config_factory) {
+  public function __construct(LanguageManagerInterface $language_manager, ConfigFactoryInterface $config_factory) {
     $this->languageManager = $language_manager;
     $this->config = $config_factory->get('system.performance');
   }

Since @Berdir has already marked this RTBC, I trust that he has already considered these points, and I defer to him. I will update the issue summary to reflect the changes being made, and remove the inappropriate tags.

Mixologic’s picture

Issue tags: +Quick fix

I have only looked at the patch, not at the change in context, so maybe I am missing something:

All of these typehint changes are part of the constructor. The constructor sets the typehinted $languageManager as a protected variable of the class. If you change the constructor typehint, you have to change where that protected variable is referenced: both in @var types as well as @return types.

@see reference has to be reviewed individually:

Each one was. All of the @see references pointed to an empty docblock that says @inheritdoc, which inherits the docs from the interface documentation. Therefore the @sees to point to the actual documentation, because that documentation was moved up to the interface when the interface was introduced.

The first change here is what I meant by changing wording in doc blocks; is this related to the change in type hinting? The second change looks wrong to me.

Camelcase LanguageManager, by itself in a docblock, refered to the concrete class "LanguageManager" - Since these can now be anything that implements a LanguageManagerInterface it is appropriate to refer to them as 'a language manager', which is the precedent everywhere else that a LanguageManagerInterface is used.

If you change the typehints you must change all documentation that refers to those typehints, and all locations where that passed in variable is referred to. Advanced IDE's will show errors if you don't, as they are often able to detect mismatches in the documented type and the TypeHinted type.

This is still definitely a "Quick fix" issue, as its virtually identical to the other five related issues where we've done pretty much exactly the same thing. I don't have any idea whether this qualifies as "novice" as that term could mean "new to coding", "new to drupal", "new to drupal 8", "new to the issue queues".

Regardless, its pretty much done, there's not much here for a novice to do.

Status: Reviewed & tested by the community » Needs work
alexpott’s picture

Issue tags: +Needs reroll

It's be great to get this done since we actually have a different implementation of LanguageManagerInterface in core - ConfigurableLanguageManager.

Sutharsan’s picture

Issue tags: -Needs reroll
FileSize
25.33 KB

Rerolled #41. No significant changes.

Sutharsan’s picture

Status: Needs work » Needs review

No remaining type hints of LanguageManager found that should be replaced.

Status: Needs review » Needs work
Sutharsan’s picture

Mixologic’s picture

Status: Needs review » Reviewed & tested by the community

LGTM

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed 7fde4cf and pushed to 8.0.x. Thanks!

  • alexpott committed 7fde4cf on 8.0.x
    Issue #2212427 by Mixologic, YesCT, Sutharsan, mgriego, icseh.,...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.