Make WordPress Core

Opened 3 months ago

Closed 3 months ago

Last modified 3 months ago

#60678 closed defect (bug) (fixed)

Definition of WP_Translation_File_MO::MAGIC_MARKER

Reported by: tmatsuur's profile tmatsuur Owned by: swissspidy's profile swissspidy
Milestone: 6.5 Priority: normal
Severity: normal Version: 6.5
Component: I18N Keywords: has-patch commit
Focuses: Cc:

Description

Currently some PHP environments may fail to load mo files.

The environment in which this problem occurred:

PHP 7.4.32 (cli) (built: Sep 28 2022 20:48:52) ( ZTS Visual C++ 2017 x86 )

I investigated the cause and found that it was due to the definition of class constants.

const MAGIC_MARKER = 0x950412de;

Dumping this constant:

var_dump( WP_Translation_File_MO::MAGIC_MARKER );

:

float(2500072158)

Due to the data type of the constant being "float" instead of "int", the detect_endian_and_validate_file method was returning false when reading the .mo file.

As a temporary measure, the WP_Translation_File_MO class has been changed as follows:

const MAGIC_MARKER = '0x950412de';

:

protected function detect_endian_and_validate_file( string $header ) {

:

	if ( (int)hexdec( self::MAGIC_MARKER ) === $big ) {
		return 'N';
	}

	if ( (int)hexdec( self::MAGIC_MARKER ) === $little ) {
		return 'V';
	}

This way, the mo file can be read and the translated content will be reflected.

I'm sure there are more appropriate ways to correct this, but I hope this helps.

Change History (13)

#1 @swissspidy
3 months ago

  • Milestone changed from Awaiting Review to 6.5
  • Owner set to swissspidy
  • Status changed from new to reviewing

#2 @swissspidy
3 months ago

  • Keywords needs-patch added

Thanks for your report!

Looks like a 32 bit vs 64 bit issue, which explains why this wasn't spotted before.

On https://3v4l.org/ you can notice it in the live preview, which is x86. There it will be a float. But as soon as you press eval();, it will be an int.

The workaround looks reasonable at first glance. Just noting that the magic marker is also used in the export() method, so that needs to be checked as well.

Another solution can be seen in the \MO::get_byteorder() method, where it's simply an integer.

#4 @tmatsuur
3 months ago

Thanks @swissspidy .

As you pointed out, this constant is also used in the export method. I had overlooked it.

#5 @tmatsuur
3 months ago

I was a little mistaken. The constant declarations do not seem to need to be changed.

const MAGIC_MARKER = 0x950412de;

:

protected function detect_endian_and_validate_file( string $header ) {

:

	if ( (int) self::MAGIC_MARKER === $big ) {
		return 'N';
	}

	if ( (int) self::MAGIC_MARKER === $little ) {
		return 'V';
	}

The above changes solved the problem.

This ticket was mentioned in PR #6216 on WordPress/wordpress-develop by @swissspidy.


3 months ago
#6

  • Keywords has-patch added; needs-patch removed

#7 @swissspidy
3 months ago

@tmatsuur Thanks!

I just opened https://github.com/WordPress/wordpress-develop/pull/6216 to apply this change. Could you please verify whether that version works for you as well?

I updated the export method as well in there.

#8 @tmatsuur
3 months ago

Thanks @swissspidy .

I will try this one right away.

#9 @tmatsuur
3 months ago

The base is WordPress 6.5 Beta 3 and has been replaced with the class-wp-translation-file-mo.php which has just been modified.

I tried this in a PHP version 7.4.x environment.

PHP 7.4.32 (cli) (built: Sep 28 2022 20:48:52) ( ZTS Visual C++ 2017 x86 )

In this environment, the translated text is displayed correctly.

As an example, "Akismet" in "Installed Plugins" is displayed as follows.

https://12net.jp/assets/img/image_20240304_01.png

For reference, the above is the case where ja.mo and admin-ja.mo exist, but if you generate ja.l10n.php and admin-ja.l10n.php, rename ja.mo and admin-ja.mo, and switch to not reading, the translated text will still be displayed correctly.

PHP version 8.0.x (64-bit) was also checked in an environment based on WordPress version 6.5 beta 3, with the updated class-wp-translation-file-mo.php replaced.

The translated text is still reflected and displayed in this environment.

I believe that, from a quick glance, the fix this time has resulted in the expected display in both environments.

#10 @swissspidy
3 months ago

  • Keywords commit added

Awesome, thanks a lot for testing!

Let's get this in for 6.5 RC 1 then. If any more issues arise we can deal with them in follow-up commits.

#12 @swissspidy
3 months ago

  • Resolution set to fixed
  • Status changed from reviewing to closed

In 57763:

I18N: Cast magic MO marker number to integer.

In gettext, 0x950412de is used to signal GNU MO files. In WP_Translation_File_MO this magic marker is used to detect whether a file uses little endian or big endian.

On 32 bit systems, this number will be interpreted by PHP as a float rather than an integer. This change adds extra casting to force an integer.

A similar change was done in the pomo library in the past, see #3780.

Props tmatsuur, swissspidy.
Fixes #60678.

#12 @tmatsuur
3 months ago

Thanks @swissspidy .

I appreciate your prompt attention to this matter.

Note: See TracTickets for help on using tickets.