I was looking into that one, and to me it looks like a mixture of a bug in loadLanguage and another abuse of re-assignation of strings variables.
The profile_error_password_short' is sprintf'ed and re-assigned to itself in Auth.subs:
$txt['profile_error_password_short'] = sprintf($txt['profile_error_password_short'], empty($modSettings['password_strength']) ? 4 : 8);
This works more or less fine, usually.
Now, let's have a little look at loadLanguage:
function loadLanguage($template_name, $lang = '', $fatal = true, $force_reload = false)
{
[...]
static $already_loaded = array();
[...]
// Do we want the English version of language file as fallback?
if (empty($modSettings['disable_language_fallback']) && $lang != 'english')
loadLanguage($template_name, 'english', false);
if (!$force_reload && isset($already_loaded[$template_name]) && $already_loaded[$template_name] == $lang)
return $lang;
With English this works fine. No problems.
What happens though when another language is added to the mix?
Let's see, calling:
loadLanguage('Errors');
$template_name is set to 'Errors' (obviously).
The first thing loadLanguage does is load the fallback language: so it calls itself specifying 'english' as language.
In that fallback run, $already_loaded[$template_name] is set to 'english'.
Then we are back to the main call and the check goes like this:
$force_reload = false => true
isset($already_loaded[$template_name]) => true
$already_loaded[$template_name] == $lang => false ($lang is 'german', while $already_loaded[$template_name] is 'english')
good, execution proceed.
Now, if we call again loadLanguage('Errors') a second time, what does it happen?
$template_name is set to 'Errors' (obviously).
The first thing loadLanguage does is load the fallback language: so it calls itself specifying 'english' as language.
In the fallback run, the check goes like this:
$force_reload = false => true
isset($already_loaded[$template_name]) => true
$already_loaded[$template_name] == $lang => false ($lang is 'english', while $already_loaded[$template_name] is 'german')
so the language file is reloaded.
Then, back again to the main call, the same as before applies:
$force_reload = false => true
isset($already_loaded[$template_name]) => true
$already_loaded[$template_name] == $lang => false ($lang is 'german', while $already_loaded[$template_name] is 'english')
and the language file is re-loaded *again*.
The fix could be to change in Load.php:
if (!$force_reload && isset($already_loaded[$template_name]) && $already_loaded[$template_name] == $lang)
if (!$force_reload && isset($already_loaded[$template_name]) && in_array($lang, $already_loaded[$template_name]))
// Remember what we have loaded, and in which language.
$already_loaded[$template_name] = $lang;
// Remember what we have loaded, and in which language.
if (!isset($already_loaded[$template_name]))
$already_loaded[$template_name] = array();
$already_loaded[$template_name][] = $lang;