Problem/Motivation
I had an interesting problem today. I was running a few SimpleTest tests from the admin/config/development/testing page (which, I realize, many people think is a bad idea, but anyway).
In my test site, at that moment, I had locale.module enabled.
The test does a WebTestBase::drupalGet() on an autocomplete page, which returns just a few bytes of data. Inside WebTestBase::curlExec(), it formats a message like this:
$message_vars = array(
'@method' => !empty($curl_options[CURLOPT_NOBODY]) ? 'HEAD' : (empty($curl_options[CURLOPT_POSTFIELDS]) ? 'GET' : 'POST'),
'@url' => isset($original_url) ? $original_url : $url,
'@status' => $status,
'@length' => format_size(strlen($this->getRawContent()))
);
$message = SafeMarkup::format('@method @url returned @status (@length).', $message_vars);
$this->assertTrue($this->getRawContent() !== FALSE, $message, 'Browser');
So $message part itself would print out fine, but the @length thing is problematic. It calls format_size(), which does this:
if ($size < Bytes::KILOBYTE) {
return \Drupal::translation()->formatPlural($size, '1 byte', '@count bytes', array(), array('langcode' => $langcode));
}
In this particular test, $size is less than 1KB, so the result is a PluralTranslatableMarkup object. And when this object tries to do a __toString() to render itself, it does this (in its render() method, which calls its getPluralIndex() method):
protected function getPluralIndex() {
if (!isset(static::$localeEnabled)) {
static::$localeEnabled = function_exists('locale_get_plural');
}
if (function_exists('locale_get_plural')) {
return locale_get_plural($this->count, $this->getOption('langcode'));
}
return -1;
}
So here's the problem. In my test site, the function locale_get_plural() does exist, so static::$localeEnabled gets value TRUE. However, when locale_get_plural() is called, it does this, somewhere down in the code:
$plural_formulas = \Drupal::service('locale.plural.formula')->getFormula($langcode);
The problem is that in the test environment, the locale module is not enabled, so that call to \Drupal::service('locale.plural.formula') fails with an exception saying the locale.plural.formula service does not exist.
Obviously this is a bit of an edge case, and not a very critical bug, but I thought I would file it anyway.
It seems like the right fix would be to have PluralTranslatableMarkup check to see if the locale.plural.formula service exists rather than (or in addition to) checking for the existence of the locale_get_plural() function... but whether this is worth doing, I do not know.
Proposed resolution
Not sure.
Remaining tasks
Not sure.
User interface changes
Tests run in UI in Simpletest will work even if Locale module is enabled in the site and not in the test.
API changes
No.
Data model changes
No.
Comments
Comment #2
jhodgdonOh. I should also mention that when this happens, the test gets into some kind of infinite loop trying to print this stuff out, and never finishes. It's normally a 2-minute test, and I waited for at least 10 minutes... it seemed to be trying to run itself over and over or else something weird happened in the printing out process or ... no idea, but it never ended.
Comment #3
jhodgdonSo looking at this piece of code from StringTranslationTrait gives an idea:
This is what pluralTranslatableMarkup::getPluralIndex() should be doing.
Comment #4
yukare commentedThis is not a duplicate of https://www.drupal.org/node/2573975 ?
Comment #5
jhodgdonYes, it is a duplicate. Thanks!
Comment #6
jhodgdon