From c79d92983200394fd676ec9b6e7b298559d88a3a Mon Sep 17 00:00:00 2001 From: Denis Ryabov Date: Sun, 9 May 2021 18:39:07 +0300 Subject: [PATCH 1/9] Add check for existing keys in JText arguments (info-level meanwhile) --- .../libraries/rules/language.php | 84 ++++++++++++++++++- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/administrator/components/com_jedchecker/libraries/rules/language.php b/administrator/components/com_jedchecker/libraries/rules/language.php index 242821d..63cbf07 100644 --- a/administrator/components/com_jedchecker/libraries/rules/language.php +++ b/administrator/components/com_jedchecker/libraries/rules/language.php @@ -44,6 +44,8 @@ class JedcheckerRulesLanguage extends JEDcheckerRule */ protected $description = 'COM_JEDCHECKER_LANG_DESC'; + protected $langKeys = array(); + /** * Initiates the search and check * @@ -61,12 +63,36 @@ class JedcheckerRulesLanguage extends JEDcheckerRule (where "tag" is a language code, e.g. en-GB, and "extension" is the extension element name, e.g. com_content) Joomla!4 allows to skip tag prefix inside of the tag directory (i.e. to name files as extension.ini and extension.sys.ini) */ - if (preg_match('#(?:^|/)([a-z]{2,3}-[A-Z]{2})[./]\w+(?:\.sys)?\.ini$#', $file, $match)) + if (preg_match('#(?:^|/)([a-z]{2,3}-[A-Z]{2})(?:[./]\w+)?(?:\.sys)?\.ini$#', $file, $match)) { + $tag = $match[1]; + // Try to validate the file - $this->find($file, $match[1]); + $this->find($file, $tag); + + if ($tag === 'en-GB') + { + $this->populateLangKeys($file); + } } } + + // Load default Joomla's translations + $files = version_compare(JVERSION, '4.0', '>=') ? array('joomla.ini', 'lib_joomla.ini') : array('en-GB.ini', 'en-GB.lib_joomla.ini'); + + foreach ($files as $file) + { + $this->populateLangKeys(JPATH_ROOT . '/language/en-GB/' . $file); + $this->populateLangKeys(JPATH_ADMINISTRATOR . '/language/en-GB/' . $file); + } + + // Check JText usage + $files = JFolder::files($this->basedir, '\.php$', true, true); + + foreach ($files as $file) + { + $this->findJText($file); + } } /** @@ -328,4 +354,58 @@ class JedcheckerRulesLanguage extends JEDcheckerRule // All checks passed. Return true return true; } + + /** + * Appends keys from INI file to the list + * + * @param string $file + * + * @return void + */ + protected function populateLangKeys($file) + { + if (is_file($file)) + { + $data = parse_ini_file($file); + + if (is_array($data)) + { + $this->langKeys = array_replace($this->langKeys, $data); + } + } + } + + /** + * Reads PHP files and checks JText arguments + * + * @param string $file - The path to the file + * + * @return boolean True on success, otherwise False. + */ + protected function findJText($file) + { + $content = file_get_contents($file); + + // Search for Text/JText calls + if (!preg_match_all('/\bJ?Text::(?:_|s?printf|alt|plural|script)\s*\(\s*([\'])([^\'"]+)\1\s*[\),]/', $content, $matches, PREG_OFFSET_CAPTURE)) + { + return true; + } + + $lines = explode("\n", $content); + + // Check all keys exist in INI files + foreach ($matches[2] as $match) + { + $key = $match[0]; + + if (!isset($this->langKeys[$key])) + { + $lineno = substr_count($content, "\n", 0, $match[1]); + $this->report->addInfo($file, JText::sprintf('COM_JEDCHECKER_LANG_UNKNOWN_KEY_IN_CODE', htmlspecialchars($key)), $lineno + 1, $lines[$lineno]); + } + } + + return true; + } } From 39608b595b836e0c00c2793014c6070dc06ec9f2 Mon Sep 17 00:00:00 2001 From: Denis Ryabov Date: Sun, 9 May 2021 18:45:39 +0300 Subject: [PATCH 2/9] Add missed constant for JText detection --- .../com_jedchecker/language/en-GB/en-GB.com_jedchecker.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/administrator/components/com_jedchecker/language/en-GB/en-GB.com_jedchecker.ini b/administrator/components/com_jedchecker/language/en-GB/en-GB.com_jedchecker.ini index bff09a4..e091f9b 100644 --- a/administrator/components/com_jedchecker/language/en-GB/en-GB.com_jedchecker.ini +++ b/administrator/components/com_jedchecker/language/en-GB/en-GB.com_jedchecker.ini @@ -138,6 +138,7 @@ COM_JEDCHECKER_LANG_UNESCAPED_QUOTE="Unescaped double quotation mark found" COM_JEDCHECKER_LANG_VARIABLE_REF="A variable reference found in the translation string." COM_JEDCHECKER_LANG_INCORRECT_ARGNUM="Probably you use incorrect placeholder format (e.g. '%1s' instead of '%1$s'), see printf's argnum format specification for details" COM_JEDCHECKER_LANG_SPACES_AROUND="Spaces around the translation string are detected" +COM_JEDCHECKER_LANG_UNKNOWN_KEY_IN_CODE="Unknown language key '%s' found in the code." COM_JEDCHECKER_TOOLBAR_CHECK="Check" COM_JEDCHECKER_TOOLBAR_CLEAR="Clear" COM_JEDCHECKER_CLICK_TO_VIEW_DETAILS="Click to View Details" From 5662e48df45f2cb065ce951b306914562b92fdf4 Mon Sep 17 00:00:00 2001 From: Denis Ryabov Date: Sun, 9 May 2021 18:46:07 +0300 Subject: [PATCH 3/9] Fix typo in language key --- .../com_jedchecker/language/en-GB/en-GB.com_jedchecker.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/components/com_jedchecker/language/en-GB/en-GB.com_jedchecker.ini b/administrator/components/com_jedchecker/language/en-GB/en-GB.com_jedchecker.ini index e091f9b..3acd8d4 100644 --- a/administrator/components/com_jedchecker/language/en-GB/en-GB.com_jedchecker.ini +++ b/administrator/components/com_jedchecker/language/en-GB/en-GB.com_jedchecker.ini @@ -131,7 +131,7 @@ COM_JEDCHECKER_LANG_TRANSLATION_ERROR="Invalid translation string" COM_JEDCHECKER_LANG_INVALID_UTF8="Invalid UTF8 string" COM_JEDCHECKER_LANG_TRANSLATION_QUOTES="All translation strings should be enclosed in double quotation marks." COM_JEDCHECKER_LANG_TRANSLATION_MISSED_LEFT_QUOTE="You have missed the left quote." -COM_JEDCHECKER_LANG_TRANSLATION_MISSED_RIGTH_QUOTE="You have missed the right quote" +COM_JEDCHECKER_LANG_TRANSLATION_MISSED_RIGHT_QUOTE="You have missed the right quote" COM_JEDCHECKER_LANG_TRANSLATION_EMPTY="Empty translation string" COM_JEDCHECKER_LANG_QQ_DEPRECATED="Usage of \"_QQ_\" is deprecated since Joomla! 3.9. Use escaped double quotes (\\\") instead" COM_JEDCHECKER_LANG_UNESCAPED_QUOTE="Unescaped double quotation mark found" From 1039b49b9babbc699e7812ac387c6d69077a4214 Mon Sep 17 00:00:00 2001 From: Denis Ryabov Date: Tue, 11 May 2021 23:52:40 +0300 Subject: [PATCH 4/9] Joomla code-style fixes --- .../com_jedchecker/libraries/rules/language.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/administrator/components/com_jedchecker/libraries/rules/language.php b/administrator/components/com_jedchecker/libraries/rules/language.php index 63cbf07..1fea4d5 100644 --- a/administrator/components/com_jedchecker/libraries/rules/language.php +++ b/administrator/components/com_jedchecker/libraries/rules/language.php @@ -44,6 +44,11 @@ class JedcheckerRulesLanguage extends JEDcheckerRule */ protected $description = 'COM_JEDCHECKER_LANG_DESC'; + /** + * Key-value map for language translations + * + * @var array + */ protected $langKeys = array(); /** @@ -358,9 +363,9 @@ class JedcheckerRulesLanguage extends JEDcheckerRule /** * Appends keys from INI file to the list * - * @param string $file + * @param string $file Language INI-file name * - * @return void + * @return void */ protected function populateLangKeys($file) { From 6ab463d32413ce2e60487a5c94d3a5a4da27bbcd Mon Sep 17 00:00:00 2001 From: Denis Ryabov Date: Tue, 11 May 2021 23:53:52 +0300 Subject: [PATCH 5/9] typo --- .../components/com_jedchecker/libraries/rules/language.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/components/com_jedchecker/libraries/rules/language.php b/administrator/components/com_jedchecker/libraries/rules/language.php index 1fea4d5..f2f6623 100644 --- a/administrator/components/com_jedchecker/libraries/rules/language.php +++ b/administrator/components/com_jedchecker/libraries/rules/language.php @@ -154,7 +154,7 @@ class JedcheckerRulesLanguage extends JEDcheckerRule $this->report->addWarning($file, JText::_('COM_JEDCHECKER_LANG_BOM_FOUND'), $startLineno); } - // Romeve BOM for further checks + // Remove BOM for further checks $line = substr($line, 3); } From 581f61efc9cb5bbbe2a2e0ef8aee71e281c92b5e Mon Sep 17 00:00:00 2001 From: Denis Ryabov Date: Mon, 10 May 2021 22:01:37 +0300 Subject: [PATCH 6/9] fix missed to-upper-case for language keys --- .../components/com_jedchecker/libraries/rules/language.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/components/com_jedchecker/libraries/rules/language.php b/administrator/components/com_jedchecker/libraries/rules/language.php index f2f6623..2e3260a 100644 --- a/administrator/components/com_jedchecker/libraries/rules/language.php +++ b/administrator/components/com_jedchecker/libraries/rules/language.php @@ -402,7 +402,7 @@ class JedcheckerRulesLanguage extends JEDcheckerRule // Check all keys exist in INI files foreach ($matches[2] as $match) { - $key = $match[0]; + $key = strtoupper($match[0]); if (!isset($this->langKeys[$key])) { From 7d7fd10cac43ab07ad0369d1a853d7bddfcdfe76 Mon Sep 17 00:00:00 2001 From: Denis Ryabov Date: Tue, 11 May 2021 23:55:25 +0300 Subject: [PATCH 7/9] Mitigate non-unix EOL to info-level --- .../components/com_jedchecker/libraries/rules/language.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/components/com_jedchecker/libraries/rules/language.php b/administrator/components/com_jedchecker/libraries/rules/language.php index 2e3260a..3b532f7 100644 --- a/administrator/components/com_jedchecker/libraries/rules/language.php +++ b/administrator/components/com_jedchecker/libraries/rules/language.php @@ -120,7 +120,7 @@ class JedcheckerRulesLanguage extends JEDcheckerRule // Check EOL format is \n (not \r or \n\r) if (strpos($content, "\r") !== false) { - $this->report->addWarning($file, JText::_('COM_JEDCHECKER_LANG_INCORRECT_EOL')); + $this->report->addInfo($file, JText::_('COM_JEDCHECKER_LANG_INCORRECT_EOL')); } $lines = file($file); From 7fe37585f2abe2e15ae8b24877da7ac24609fbe6 Mon Sep 17 00:00:00 2001 From: Denis Ryabov Date: Tue, 11 May 2021 23:56:48 +0300 Subject: [PATCH 8/9] fix displaying of "\n" in the message --- .../components/com_jedchecker/libraries/rules/language.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/components/com_jedchecker/libraries/rules/language.php b/administrator/components/com_jedchecker/libraries/rules/language.php index 3b532f7..10a48d2 100644 --- a/administrator/components/com_jedchecker/libraries/rules/language.php +++ b/administrator/components/com_jedchecker/libraries/rules/language.php @@ -120,7 +120,7 @@ class JedcheckerRulesLanguage extends JEDcheckerRule // Check EOL format is \n (not \r or \n\r) if (strpos($content, "\r") !== false) { - $this->report->addInfo($file, JText::_('COM_JEDCHECKER_LANG_INCORRECT_EOL')); + $this->report->addInfo($file, JText::_('COM_JEDCHECKER_LANG_INCORRECT_EOL', false, false)); } $lines = file($file); From 7f00263488ed786b84a5b66e046578ee2f849482 Mon Sep 17 00:00:00 2001 From: Denis Ryabov Date: Mon, 17 May 2021 23:49:10 +0300 Subject: [PATCH 9/9] Fix _QQ_ match (to load language file in rare case of disabled parse_ini_file) --- .../com_jedchecker/language/en-GB/en-GB.com_jedchecker.ini | 2 +- .../components/com_jedchecker/libraries/rules/language.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/administrator/components/com_jedchecker/language/en-GB/en-GB.com_jedchecker.ini b/administrator/components/com_jedchecker/language/en-GB/en-GB.com_jedchecker.ini index 3acd8d4..ed5ed4c 100644 --- a/administrator/components/com_jedchecker/language/en-GB/en-GB.com_jedchecker.ini +++ b/administrator/components/com_jedchecker/language/en-GB/en-GB.com_jedchecker.ini @@ -133,7 +133,7 @@ COM_JEDCHECKER_LANG_TRANSLATION_QUOTES="All translation strings should be enclos COM_JEDCHECKER_LANG_TRANSLATION_MISSED_LEFT_QUOTE="You have missed the left quote." COM_JEDCHECKER_LANG_TRANSLATION_MISSED_RIGHT_QUOTE="You have missed the right quote" COM_JEDCHECKER_LANG_TRANSLATION_EMPTY="Empty translation string" -COM_JEDCHECKER_LANG_QQ_DEPRECATED="Usage of \"_QQ_\" is deprecated since Joomla! 3.9. Use escaped double quotes (\\\") instead" +COM_JEDCHECKER_LANG_QQDEPRECATED="Usage of "_QQ_" is deprecated since Joomla! 3.9. Use escaped double quotes (\\") instead" COM_JEDCHECKER_LANG_UNESCAPED_QUOTE="Unescaped double quotation mark found" COM_JEDCHECKER_LANG_VARIABLE_REF="A variable reference found in the translation string." COM_JEDCHECKER_LANG_INCORRECT_ARGNUM="Probably you use incorrect placeholder format (e.g. '%1s' instead of '%1$s'), see printf's argnum format specification for details" diff --git a/administrator/components/com_jedchecker/libraries/rules/language.php b/administrator/components/com_jedchecker/libraries/rules/language.php index 10a48d2..be7160c 100644 --- a/administrator/components/com_jedchecker/libraries/rules/language.php +++ b/administrator/components/com_jedchecker/libraries/rules/language.php @@ -303,7 +303,7 @@ class JedcheckerRulesLanguage extends JEDcheckerRule // Check for legacy "_QQ_" code (deprecated since Joomla! 3.9 in favour of escaped double quote \"; removed in Joomla! 4) if (strpos($value, '"_QQ_"') !== false) { - $this->report->addCompat($file, JText::_('COM_JEDCHECKER_LANG_QQ_DEPRECATED'), $startLineno, $line); + $this->report->addCompat($file, JText::_('COM_JEDCHECKER_LANG_QQDEPRECATED'), $startLineno, $line); } // Convert "_QQ_" to escaped quotes for further analysis