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 0fac074..88c4545 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 @@ -96,7 +96,7 @@ 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" COM_JEDCHECKER_LANG_VARIABLE_REF="A variable reference found in the translation string." -COM_JEDCHECKER_LANG_RECOMMEND_ARGNUM="Placeholders may have another order in some languages. To simplify work of translators, it's recommended to use argnum specification (e.g. '%1$s'), see https://www.php.net/manual/en/function.sprintf.php for details" +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_TOOLBAR_CHECK="Check" COM_JEDCHECKER_TOOLBAR_CLEAR="Clear" COM_JEDCHECKER_CLICK_TO_VIEW_DETAILS="Click to View Details" diff --git a/administrator/components/com_jedchecker/libraries/rules/language.php b/administrator/components/com_jedchecker/libraries/rules/language.php index eec3725..5287f00 100644 --- a/administrator/components/com_jedchecker/libraries/rules/language.php +++ b/administrator/components/com_jedchecker/libraries/rules/language.php @@ -229,16 +229,28 @@ class JedcheckerRulesLanguage extends JEDcheckerRule $this->report->addWarning($file, JText::_('COM_JEDCHECKER_LANG_VARIABLE_REF'), $startLineno, $line); } - // Count %... formats in the string - $countAll = preg_match_all('/(?<=^|[^%])%(?=[-+0 ]?\w)/', $value); + // The code below detects incorrect format of numbered placeholders (e.g. "%1s" instead of "%1$s") - // Count %n$... (argnum) formats in the string - $countArgnum = preg_match_all('/(?<=^|[^%])%\d+\$/', $value); + // Count numbered placeholders in the string (e.g. "%1s") + $count = preg_match_all('/(?<=^|[^%])%(\d+)\w/', $value, $matches); - if ($countAll > 1 && $countArgnum < $countAll) + if ($count) { - // @todo It's not mentioned in docs - $this->report->addInfo($file, JText::_('COM_JEDCHECKER_LANG_RECOMMEND_ARGNUM'), $startLineno, $line); + // To avoid false-positives (e.g. %10s for a ten-characters-wide output string in a CLI), + // we check that placeholder numbers form a sequence from 1 to N. + + $maxNumber = 0; + + foreach ($matches as $match) + { + $maxNumber = max($maxNumber, (int) $match[1]); + } + + // If placeholder numbers form a sequence, the maximal value is equal to the number of elements + if ($maxNumber === $count) + { + $this->report->addWarning($file, JText::_('COM_JEDCHECKER_LANG_INCORRECT_ARGNUM'), $startLineno, $line); + } } }