Follow-up to #2583041: GD toolkit & operations should check for available memory
Problem
File common.inc, function format_size()
This function either calls:
<?php
\Drupal::translation()->formatPlural($size, '1 byte', '@count bytes', array(), array('langcode' => $langcode));
?>
or:
<?php
$options = ['langcode' => $langcode];
...
return new TranslatableMarkup('@size ...', $args, $options);
?>
However, the parameter $langcode may be null or absent with a default of null. in which case the $option array contains an entry 'langcode' with a value of null.
Deeper down this leads to:
- Missing merging in defaults (core\lib\Drupal\Core\StringTranslation\TranslationManager.php:doTranslate():
// Merge in options defaults.
$options = $options + [
'langcode' => $this->defaultLangcode,
'context' => '',
];
- Checking/assigning key NULL (core\lib\Drupal\Core\StringTranslation\Translator\StaticTranslation.php:getStringTranslation()):
if (!isset($this->translations[$langcode])) {
$this->translations[$langcode] = $this->getLanguage($langcode);
}
- Checking/assigning key NULL; implicitly converting NULL to string; Missing cache (or even using cache built in another language?) via core\modules\locale\src\LocaleTranslation.php:getStringTranslation() and core\modules\locale\src\LocaleLookup.php:getCid():
if (!isset($this->translations[$langcode][$context])) {
$this->translations[$langcode][$context] = new LocaleLookup($langcode, $context, $this->storage, $this->cache, $this->lock, $this->configFactory, $this->languageManager, $this->requestStack);
}
$this->cid = "locale:{$this->langcode}:{$this->context}:$rids";
From these examples it may be clear that in Drupal translation:
- A parameter $langcode may be left out or null if explicitly indicated so.
- A parameter $langcode may not be null (or the empty string ) if it is documented as being of type string.
- A key 'langcode' in a $options parameter of type array may be absent but not null.
Errors against this pattern are also found in:
- \Drupal\Core\Datetime\DateFormatter::formatInterval()
- \Drupal\Core\Datetime\DrupalDateTime::format(), formatDiff()
- File system.tokens.inc, function system_tokens(), call to formatTimeDiffSince
- \Drupal\Core\Validation\DrupalTranslator
Proposed resolution
Check for null before creating a key 'langcode' in the options array, leave it absent if null.
Remaining tasks
- Decide: is this indeed an error in the calling functions or should we make the receiving API's more lax?
- Do we need to better document this pattern?
- Write patch for all cases.
- Review patch.
- Accept patch.
User interface changes
None.
API changes
None.
Data model changes
None.