WPML String Translation: fallback translation loading uses inconsistent domain
-
WPML String Translation: fallback translation loading uses inconsistent domain casing and builds unsafe relative paths when registry returns
falseEnvironment
- WordPress: 6.9.4
- WPML String Translation: 3.5.2
- WPML Multilingual CMS: 4.9.3
- WooCommerce Multilingual: 5.5.5
- PHP: 8.4
- Web server: LiteSpeed
open_basedir: active for web requests
Problem
WPML String Translation triggers repeated PHP warnings during translation loading:
PHP Warning: file_exists(): open_basedir restriction in effect. File(WordPress-en_US.mo) is not within the allowed path(s) PHP Warning: file_exists(): open_basedir restriction in effect. File(WordPress-en_US.l10n.php) is not within the allowed path(s) PHP Warning: file_exists(): open_basedir restriction in effect. File(WordPress-de_DE.mo) is not within the allowed path(s) PHP Warning: file_exists(): open_basedir restriction in effect. File(WordPress-de_DE.l10n.php) is not within the allowed path(s) PHP Warning: realpath(): open_basedir restriction in effect. File(/usr/local/lsws/fcgi-bin) is not within the allowed path(s)This is not limited to the
WordPressdomain. The same casing/filename issue can affect other WPML String Translation domains such asWP Endpoints.Where It Happens
wpml-string-translation/classes/MO/Hooks/LoadTranslationFile.phpIn
LoadTranslationFile::getDefaultWordPressTranslationPath():$defaultPathDirectory = $wp_textdomain_registry->get( $domain, $locale ); $defaultPathFile = "{$defaultPathDirectory}{$domain}-{$locale}.mo";When
$wp_textdomain_registry->get( $domain, $locale )returnsfalse, WPML still concatenates it into a filename. PHP convertsfalseto an empty string, producing relative paths like:WordPress-en_US.mo WordPress-en_US.l10n.php WP Endpoints-en_US.mo WP Endpoints-en_US.l10n.phpWith LiteSpeed, the current working directory can be
/usr/local/lsws/fcgi-bin, sofile_exists()/realpath()on these relative paths triggersopen_basedirwarnings.Diagnostics
The WordPress textdomain registry returns:
WordPress + pl_PL => /home/.../public/app/languages/wpml/ WordPress + de_DE => false WordPress + en_US => falseWPML-generated String Translation files exist, but filenames are normalized to lowercase:
app/languages/wpml/wordpress-pl_PL.l10n.php app/languages/wpml/wordpress-de_DE.l10n.php app/languages/wpml/wordpress-en_US.l10n.php app/languages/wpml/wp endpoints-pl_PL.l10n.phpQuery Monitor confirms WPML loads the String Translation files using these lowercase filenames:
WordPress php WPML\S\M\J\MO::loadTextDomain() app/languages/wpml/wordpress-pl_PL.l10n.php WordPress php WPML\S\M\J\MO::loadTextDomain() app/languages/wpml/wordpress-en_US.l10n.phpSo the warning is not caused by missing WPML String Translation files. It is caused by the additional fallback lookup for default translation files using the original domain casing.
Root Cause
WPML stores/uses domains such as:
WordPress WP EndpointsFor example, the scanner fallback uses:
$domain = $domain ? $domain : 'WordPress';But WPML writes generated translation files with lowercased domain filenames:
strtolower( $domain ) . '-' . $localeSo:
WordPress -> wordpress-en_US.l10n.php WP Endpoints -> wp endpoints-pl_PL.l10n.phpHowever,
LoadTranslationFile::getDefaultWordPressTranslationPath()searches using the original domain casing:WordPress-en_US.l10n.php WP Endpoints-pl_PL.l10n.phpThis creates a mismatch between the domain name and the generated filename. When the registry cannot resolve a path, the missing guard also causes unsafe relative path checks.
Expected Behavior
WPML should:
- Never concatenate a
falseregistry result into a filesystem path. - Never call
file_exists()/realpath()on relative fallback paths produced from unresolved registry data. - Use the same filename normalization when reading fallback/generated translation files as it uses when writing them.
- Handle domains with uppercase letters and spaces consistently, including
WordPressandWP Endpoints.
Required Fix
LoadTranslationFile::getDefaultWordPressTranslationPath()should first validate the registry result:$defaultPathDirectory = $wp_textdomain_registry->get( $domain, $locale ); if ( ! is_string( $defaultPathDirectory ) || '' === $defaultPathDirectory ) { return null; }Then fallback lookup must use the same normalized filename convention WPML uses when generating files:
$normalizedDomain = strtolower( str_replace( '/', '-', $domain ) );and check normalized filenames as well as any standard WordPress filename conventions relevant to core/plugin/theme translation files:
{$normalizedDomain}-{$locale}.mo {$normalizedDomain}-{$locale}.l10n.phpThis needs to cover domains like:
WordPress WP EndpointsImpact
- Repeated PHP warnings in production logs.
- Issue appears in web requests where
open_basediris active. - The actual WPML String Translation files can still load correctly, but the fallback/default translation lookup is unsafe and inconsistent.
- Affects domains with uppercase letters and spaces, not only
WordPress.
You must be logged in to reply to this topic.