From 7c11d1ebf5f7d3ded333ce931c9c07e048ec5e2d Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 30 Apr 2024 08:39:07 +0000 Subject: [PATCH] I18N: Actually add all the files for [58061], not just the test fixtures. Improve support for using only PHP translation files. This builds on top of the PHP translation file support added in WordPress 6.5, improving the behavior for projects using solely `.l10n.php` translation files and no `.mo.` and `.po` files. Updates `wp_get_installed_translations()`, which is used when updating language packs and when uninstalling plugins/themes (to remove the translations again), to look for PHP translation files and read metadata from them. Additionally, the file lookup is now cached thanks to using `WP_Textdomain_Registry`. Updates `Language_Pack_Upgrader::check_package()` to allow language packs that only contain PHP translation files. While WordPress.org continues to serve `.mo` and `.po` files, third-party services might want to only use the PHP file format. See #60554. Built from https://develop.svn.wordpress.org/trunk@58062 git-svn-id: http://core.svn.wordpress.org/trunk@57527 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- .../includes/class-language-pack-upgrader.php | 20 +++-- wp-includes/l10n.php | 80 ++++++++++++++----- wp-includes/version.php | 2 +- 3 files changed, 77 insertions(+), 25 deletions(-) diff --git a/wp-admin/includes/class-language-pack-upgrader.php b/wp-admin/includes/class-language-pack-upgrader.php index 855dbe642a..6f7cf742bd 100644 --- a/wp-admin/includes/class-language-pack-upgrader.php +++ b/wp-admin/includes/class-language-pack-upgrader.php @@ -332,26 +332,34 @@ class Language_Pack_Upgrader extends WP_Upgrader { // Check that the folder contains a valid language. $files = $wp_filesystem->dirlist( $remote_source ); - // Check to see if a .po and .mo exist in the folder. - $po = false; - $mo = false; + // Check to see if the expected files exist in the folder. + $po = false; + $mo = false; + $php = false; foreach ( (array) $files as $file => $filedata ) { if ( str_ends_with( $file, '.po' ) ) { $po = true; } elseif ( str_ends_with( $file, '.mo' ) ) { $mo = true; + } elseif ( str_ends_with( $file, '.l10n.php' ) ) { + $php = true; } } + if ( $php ) { + return $source; + } + if ( ! $mo || ! $po ) { return new WP_Error( 'incompatible_archive_pomo', $this->strings['incompatible_archive'], sprintf( - /* translators: 1: .po, 2: .mo */ - __( 'The language pack is missing either the %1$s or %2$s files.' ), + /* translators: 1: .po, 2: .mo, 3: .l10n.php */ + __( 'The language pack is missing either the %1$s, %2$s, or %3$s files.' ), '.po', - '.mo' + '.mo', + '.l10n.php' ) ); } diff --git a/wp-includes/l10n.php b/wp-includes/l10n.php index 3b99ff848b..9e2a86a759 100644 --- a/wp-includes/l10n.php +++ b/wp-includes/l10n.php @@ -1505,25 +1505,25 @@ function get_available_languages( $dir = null ) { * * @since 3.7.0 * + * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry. + * * @param string $type What to search for. Accepts 'plugins', 'themes', 'core'. * @return array Array of language data. */ function wp_get_installed_translations( $type ) { + global $wp_textdomain_registry; + if ( 'themes' !== $type && 'plugins' !== $type && 'core' !== $type ) { return array(); } - $dir = 'core' === $type ? '' : "/$type"; + $dir = 'core' === $type ? WP_LANG_DIR : WP_LANG_DIR . "/$type"; - if ( ! is_dir( WP_LANG_DIR ) ) { + if ( ! is_dir( $dir ) ) { return array(); } - if ( $dir && ! is_dir( WP_LANG_DIR . $dir ) ) { - return array(); - } - - $files = scandir( WP_LANG_DIR . $dir ); + $files = $wp_textdomain_registry->get_language_files_from_path( $dir ); if ( ! $files ) { return array(); } @@ -1531,16 +1531,7 @@ function wp_get_installed_translations( $type ) { $language_data = array(); foreach ( $files as $file ) { - if ( '.' === $file[0] || is_dir( WP_LANG_DIR . "$dir/$file" ) ) { - continue; - } - if ( ! str_ends_with( $file, '.po' ) ) { - continue; - } - if ( ! preg_match( '/(?:(.+)-)?([a-z]{2,3}(?:_[A-Z]{2})?(?:_[a-z0-9]+)?).po/', $file, $match ) ) { - continue; - } - if ( ! in_array( substr( $file, 0, -3 ) . '.mo', $files, true ) ) { + if ( ! preg_match( '/(?:(.+)-)?([a-z]{2,3}(?:_[A-Z]{2})?(?:_[a-z0-9]+)?)\.(?:mo|l10n\.php)/', basename( $file ), $match ) ) { continue; } @@ -1548,7 +1539,25 @@ function wp_get_installed_translations( $type ) { if ( '' === $textdomain ) { $textdomain = 'default'; } - $language_data[ $textdomain ][ $language ] = wp_get_pomo_file_data( WP_LANG_DIR . "$dir/$file" ); + + if ( str_ends_with( $file, '.mo' ) ) { + $pofile = substr_replace( $file, '.po', - strlen( '.mo' ) ); + + if ( ! file_exists( $pofile ) ) { + continue; + } + + $language_data[ $textdomain ][ $language ] = wp_get_pomo_file_data( $pofile ); + } else { + $pofile = substr_replace( $file, '.po', - strlen( '.l10n.php' ) ); + + // If both a PO and a PHP file exist, prefer the PO file. + if ( file_exists( $pofile ) ) { + continue; + } + + $language_data[ $textdomain ][ $language ] = wp_get_l10n_php_file_data( $file ); + } } return $language_data; } @@ -1578,6 +1587,41 @@ function wp_get_pomo_file_data( $po_file ) { return $headers; } +/** + * Extracts headers from a PHP translation file. + * + * @since 6.6.0 + * + * @param string $php_file Path to a `.l10n.php` file. + * @return string[] Array of file header values keyed by header name. + */ +function wp_get_l10n_php_file_data( $php_file ) { + $data = (array) include $php_file; + + unset( $data['messages'] ); + $headers = array( + 'POT-Creation-Date' => 'pot-creation-date', + 'PO-Revision-Date' => 'po-revision-date', + 'Project-Id-Version' => 'project-id-version', + 'X-Generator' => 'x-generator', + ); + + $result = array( + 'POT-Creation-Date' => '', + 'PO-Revision-Date' => '', + 'Project-Id-Version' => '', + 'X-Generator' => '', + ); + + foreach ( $headers as $po_header => $php_header ) { + if ( isset( $data[ $php_header ] ) ) { + $result[ $po_header ] = $data[ $php_header ]; + } + } + + return $result; +} + /** * Displays or returns a Language selector. * diff --git a/wp-includes/version.php b/wp-includes/version.php index 1dc961be77..09fb338a07 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -16,7 +16,7 @@ * * @global string $wp_version */ -$wp_version = '6.6-alpha-58061'; +$wp_version = '6.6-alpha-58062'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.