diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/DictionaryTest.php b/dev/tests/integration/testsuite/Magento/Framework/App/Language/DictionaryTest.php index 363f84627350f..bc299053bd4fe 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/App/Language/DictionaryTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/DictionaryTest.php @@ -63,7 +63,9 @@ public function dictionaryDataProvider() // Second case with inheritance of package with the same language code 'a case with inheritance similar language code' => $this->getDataInheritanceWitSimilarCode(), // Third case with circular inheritance, when two packages depend on each other - 'a case with circular inheritance' => $this->getDataCircularInheritance() + 'a case with circular inheritance' => $this->getDataCircularInheritance(), + // Fourth case with multiple inheritance from dev docs + 'a case with multiple inheritance from dev docs' => $this->getDataMultipleInheritanceFromDevDocs() ]; } @@ -113,7 +115,7 @@ private function getDataCircularInheritance() { return [ // Dictionary that will be requested - 'language_code' => 'en_US', + 'language_code' => 'en_AZ', // Expected merged dictionary data 'expectation' => [ 'one' => '1.0', @@ -123,4 +125,48 @@ private function getDataCircularInheritance() ] ]; } + + /** + * If a language package inherits from two packages: + * ... + * en_AK + * ... + * + * + * ... + * + * In the preceding example: + * language_package_one inherits from en_au_package and en_au_package inherits from en_ie_package + * language_package_two inherits from en_ca_package and en_ca_package inherits from en_us_package + * + * If the Magento application cannot find word or phrase in the en_AK package, + * it looks in other packages in following sequence: + * parent-package-one/language_package_one + * /en_au_package + * /en_ie_package + * parent-package-two/language_package_two + * /en_ca_package + * /en_us_package + * + * @return array + */ + private function getDataMultipleInheritanceFromDevDocs() + { + return [ + // Dictionary that will be requested + 'language_code' => 'en_AK', + // Expected merged dictionary data + 'expectation' => [ + 'one' => 'en_us_package_one', + 'two' => 'en_ca_package_two', + 'three' => 'language_package_two_three', + 'four' => 'en_ie_package_four', + 'five' => 'en_au_package_five', + 'six' => 'language_package_one_six', + 'seven' => 'en_ak_seven', + 'eight' => 'en_ak_eight', + 'nine' => 'en_ak_nine', + ] + ]; + } } diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_us/a.csv b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_az/a.csv similarity index 100% rename from dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_us/a.csv rename to dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_az/a.csv diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_us/b.csv b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_az/b.csv similarity index 100% rename from dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_us/b.csv rename to dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_az/b.csv diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_us/language.xml b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_az/language.xml similarity index 86% rename from dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_us/language.xml rename to dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_az/language.xml index a4c5630d5fcd9..3cc5d8965c2e8 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_us/language.xml +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_az/language.xml @@ -6,8 +6,8 @@ */ --> - en_US + en_AZ bar - en_us + en_az 0 diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_us/registration.php b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_az/registration.php similarity index 92% rename from dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_us/registration.php rename to dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_az/registration.php index 7f792bf5941ca..41e17fbcf515d 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_us/registration.php +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_az/registration.php @@ -6,4 +6,4 @@ use Magento\Framework\Component\ComponentRegistrar; -ComponentRegistrar::register(ComponentRegistrar::LANGUAGE, 'bar_en_us', __DIR__); +ComponentRegistrar::register(ComponentRegistrar::LANGUAGE, 'bar_en_az', __DIR__); diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_gb/language.xml b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_gb/language.xml index faf531fbf5cc2..736e9dbe738d7 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_gb/language.xml +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/bar/en_gb/language.xml @@ -10,5 +10,5 @@ bar en_gb 100 - + diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/baz/en_gb/1.csv b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/baz/en_gb/1.csv index ea501f9d96944..61ef9dd8a49b3 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/baz/en_gb/1.csv +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/baz/en_gb/1.csv @@ -1 +1,5 @@ -four and 5/10,4.5 \ No newline at end of file +one,1.00 +two,2.00 +three,3.00 +four,4.00 +four and 5/10,4.5 diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/devdoc/en_ak/1.csv b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/devdoc/en_ak/1.csv new file mode 100644 index 0000000000000..8ed274ad7d886 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/devdoc/en_ak/1.csv @@ -0,0 +1,3 @@ +seven,en_ak_seven +eight,en_ak_eight +nine,en_ak_nine diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/devdoc/en_ak/language.xml b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/devdoc/en_ak/language.xml new file mode 100644 index 0000000000000..d0db854f329d0 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/devdoc/en_ak/language.xml @@ -0,0 +1,15 @@ + + + + en_AK + devdoc + en_ak + 0 + + + diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/devdoc/en_ak/registration.php b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/devdoc/en_ak/registration.php new file mode 100644 index 0000000000000..13b498edcd0aa --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/devdoc/en_ak/registration.php @@ -0,0 +1,9 @@ + - en_US + en_AZ first - en_us + en_az 0 diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/en_us/registration.php b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/en_az/registration.php similarity index 91% rename from dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/en_us/registration.php rename to dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/en_az/registration.php index 48dfbf20c9f26..85e88eb4546ce 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/en_us/registration.php +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/first/en_az/registration.php @@ -6,4 +6,4 @@ use Magento\Framework\Component\ComponentRegistrar; -ComponentRegistrar::register(ComponentRegistrar::LANGUAGE, 'first_en_us', __DIR__); +ComponentRegistrar::register(ComponentRegistrar::LANGUAGE, 'first_en_az', __DIR__); diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_au_package/1.csv b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_au_package/1.csv new file mode 100644 index 0000000000000..f1d7dc7c106c7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_au_package/1.csv @@ -0,0 +1,5 @@ +five,en_au_package_five +six,en_au_package_six +seven,en_au_package_seven +eight,en_au_package_eight +nine,en_au_package_nine diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_au_package/language.xml b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_au_package/language.xml new file mode 100644 index 0000000000000..64d558d9c1d63 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_au_package/language.xml @@ -0,0 +1,14 @@ + + + + en_US + parent-package-one + en_au_package + 0 + + diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_au_package/registration.php b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_au_package/registration.php new file mode 100644 index 0000000000000..664a6d34a814b --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_au_package/registration.php @@ -0,0 +1,9 @@ + + + + en_US + parent-package-one + en_ie_package + 0 + diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_ie_package/registration.php b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_ie_package/registration.php new file mode 100644 index 0000000000000..81ae45c3d5a40 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/en_ie_package/registration.php @@ -0,0 +1,9 @@ + + + + en_US + parent-package-one + language_package_one + 0 + + diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/language_package_one/registration.php b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/language_package_one/registration.php new file mode 100644 index 0000000000000..0432f835f0849 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-one/language_package_one/registration.php @@ -0,0 +1,9 @@ + + + + en_US + parent-package-two + en_ca_package + 0 + + diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_ca_package/registration.php b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_ca_package/registration.php new file mode 100644 index 0000000000000..b87032884f7db --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_ca_package/registration.php @@ -0,0 +1,9 @@ + + + + en_US + parent-package-two + en_us_package + 0 + diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_us_package/registration.php b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_us_package/registration.php new file mode 100644 index 0000000000000..48ed54033a96e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/en_us_package/registration.php @@ -0,0 +1,9 @@ + + + + en_US + parent-package-two + language_package_two + 0 + + diff --git a/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/language_package_two/registration.php b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/language_package_two/registration.php new file mode 100644 index 0000000000000..f7eb7d2373a29 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/App/Language/_files/parent-package-two/language_package_two/registration.php @@ -0,0 +1,9 @@ +second en_gb 0 - + diff --git a/lib/internal/Magento/Framework/App/Language/Dictionary.php b/lib/internal/Magento/Framework/App/Language/Dictionary.php index d9a5ccb00d892..b4a6fdc1b5ce3 100644 --- a/lib/internal/Magento/Framework/App/Language/Dictionary.php +++ b/lib/internal/Magento/Framework/App/Language/Dictionary.php @@ -103,7 +103,9 @@ public function getDictionary($languageCode) foreach ($languages as $languageConfig) { $this->collectInheritedPacks($languageConfig, $packs); } - uasort($packs, [$this, 'sortInherited']); + + // Get sorted packs + $packs = $this->getSortedPacks($packs); // Merge all packages of translation to one dictionary $result = []; @@ -118,6 +120,37 @@ public function getDictionary($languageCode) return $result; } + /** + * Get sorted packs + * + * First level packs (inheritance_level eq 0) sort by 'sort order' (ascending) + * Inherited packs has the same order as declared in parent config (language.xml) + * + * @param array $allPacks + * + * @return array + */ + private function getSortedPacks($allPacks) + { + // Get first level (inheritance_level) packs and sort by provided sort order (descending) + $firstLevelPacks = array_filter( + $allPacks, + function ($pack) { + return $pack['inheritance_level'] === 0; + } + ); + uasort($firstLevelPacks, [$this, 'sortPacks']); + + // Add inherited packs + $sortedPacks = []; + foreach ($firstLevelPacks as $pack) { + $this->addInheritedPacks($allPacks, $pack, $sortedPacks); + } + + // Reverse array: the first element has the lowest priority, the last one - the highest + return array_reverse($sortedPacks, true); + } + /** * Line up (flatten) a tree of inheritance of language packs * @@ -152,28 +185,46 @@ private function collectInheritedPacks($languageConfig, &$result, $level = 0, ar } /** - * Sub-routine for custom sorting packs using inheritance level and sort order + * Add inherited packs to sorted packs * - * First sort by inheritance level descending, then by sort order ascending + * @param array $packs + * @param array $pack + * @param array $sortedPacks + * + * @return void + */ + private function addInheritedPacks($packs, $pack, &$sortedPacks) + { + if (isset($sortedPacks[$pack['key']])) { + return; + } + + $sortedPacks[$pack['key']] = $pack; + foreach ($pack['language']->getUses() as $reuse) { + $packKey = implode('|', [$reuse['vendor'], $reuse['package']]); + if (isset($packs[$packKey])) { + $this->addInheritedPacks($packs, $packs[$packKey], $sortedPacks); + } + } + } + + /** + * Sub-routine for custom sorting packs using sort order (descending) * * @param array $current * @param array $next + * * @return int * @SuppressWarnings(PHPMD.UnusedPrivateMethod) */ - private function sortInherited($current, $next) + private function sortPacks($current, $next) { - if ($current['inheritance_level'] > $next['inheritance_level']) { - return -1; - } elseif ($current['inheritance_level'] < $next['inheritance_level']) { - return 1; - } if ($current['sort_order'] > $next['sort_order']) { - return 1; - } elseif ($current['sort_order'] < $next['sort_order']) { return -1; + } elseif ($current['sort_order'] < $next['sort_order']) { + return 1; } - return strcmp($current['key'], $next['key']); + return strcmp($next['key'], $current['key']); } /**