I18N: Add JavaScript translation support.

Adds the `wp_set_script_translations()` function which registers translations for a JavaScript file. This function takes a handle, domain and optionally a path and ensures JavaScript translation files are loaded if they exist.

Merges [43825,43828,43859,43898] from the 5.0 branch to trunk.

Props herregroen, atimmer, omarreiss, nerrad, swissspidy, ocean90, georgestephanis.
Fixes #45103, #45256.


Built from https://develop.svn.wordpress.org/trunk@44169


git-svn-id: http://core.svn.wordpress.org/trunk@43999 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Gary Pendergast 2018-12-14 05:52:52 +00:00
parent 4739b8147b
commit f46fbae857
5 changed files with 203 additions and 2 deletions

View File

@ -67,6 +67,22 @@ class _WP_Dependency {
*/
public $extra = array();
/**
* Translation textdomain set for this dependency.
*
* @since 5.0.0
* @var string
*/
public $textdomain;
/**
* Translation path set for this dependency.
*
* @since 5.0.0
* @var string
*/
public $translations_path;
/**
* Setup dependencies.
*
@ -96,4 +112,12 @@ class _WP_Dependency {
return true;
}
public function set_translations( $domain, $path = null ) {
if ( ! is_string( $domain ) ) {
return false;
}
$this->textdomain = $domain;
$this->translations_path = $path;
return true;
}
}

View File

@ -330,6 +330,11 @@ class WP_Scripts extends WP_Dependencies {
return true;
}
$translations = $this->print_translations( $handle, false );
if ( $translations ) {
$translations = sprintf( "<script type='text/javascript'>\n%s\n</script>\n", $translations );
}
if ( ! preg_match( '|^(https?:)?//|', $src ) && ! ( $this->content_url && 0 === strpos( $src, $this->content_url ) ) ) {
$src = $this->base_url . $src;
}
@ -345,7 +350,7 @@ class WP_Scripts extends WP_Dependencies {
return true;
}
$tag = "{$cond_before}{$before_handle}<script type='text/javascript' src='$src'></script>\n{$after_handle}{$cond_after}";
$tag = "{$translations}{$cond_before}{$before_handle}<script type='text/javascript' src='$src'></script>\n{$after_handle}{$cond_after}";
/**
* Filters the HTML script tag of an enqueued script.
@ -490,6 +495,67 @@ class WP_Scripts extends WP_Dependencies {
return parent::set_group( $handle, $recursion, $grp );
}
/**
* Sets a translation textdomain.
*
* @since 5.0.0
*
* @param string $handle Name of the script to register a translation domain to.
* @param string $domain The textdomain.
* @param string $path Optional. The full file path to the directory containing translation files.
*
* @return bool True if the textdomain was registered, false if not.
*/
public function set_translations( $handle, $domain, $path = null ) {
if ( ! isset( $this->registered[ $handle ] ) ) {
return false;
}
/** @var \_WP_Dependency $obj */
$obj = $this->registered[ $handle ];
if ( ! in_array( 'wp-i18n', $obj->deps, true ) ) {
$obj->deps[] = 'wp-i18n';
}
return $obj->set_translations( $domain, $path );
}
/**
* Prints translations set for a specific handle.
*
* @since 5.0.0
*
* @param string $handle Name of the script to add the inline script to. Must be lowercase.
* @param bool $echo Optional. Whether to echo the script instead of just returning it.
* Default true.
* @return string|false Script on success, false otherwise.
*/
public function print_translations( $handle, $echo = true ) {
if ( ! isset( $this->registered[ $handle ] ) || empty( $this->registered[ $handle ]->textdomain ) ) {
return false;
}
$domain = $this->registered[ $handle ]->textdomain;
$path = $this->registered[ $handle ]->translations_path;
$json_translations = load_script_textdomain( $handle, $domain, $path );
if ( ! $json_translations ) {
// Register empty locale data object to ensure the domain still exists.
$json_translations = '{ "locale_data": { "messages": { "": {} } } }';
}
$output = '(function( translations ){' .
'wp.i18n.setLocaleData( translations.locale_data, "' . $domain . '" );' .
'})(' . $json_translations . ');';
if ( $echo ) {
printf( "<script type='text/javascript'>\n%s\n</script>\n", $output );
}
return $output;
}
/**
* Determines script dependencies.
*

View File

@ -200,6 +200,32 @@ function wp_localize_script( $handle, $object_name, $l10n ) {
return $wp_scripts->localize( $handle, $object_name, $l10n );
}
/**
* Sets translated strings for a script.
*
* Works only if the script has already been added.
*
* @see WP_Scripts::set_translations()
* @global WP_Scripts $wp_scripts The WP_Scripts object for printing scripts.
*
* @since 5.0.0
*
* @param string $handle Script handle the textdomain will be attached to.
* @param string $domain The textdomain.
* @param string $path Optional. The full file path to the directory containing translation files.
*
* @return bool True if the textdomain was successfully localized, false otherwise.
*/
function wp_set_script_translations( $handle, $domain, $path = null ) {
global $wp_scripts;
if ( ! ( $wp_scripts instanceof WP_Scripts ) ) {
_wp_scripts_maybe_doing_it_wrong( __FUNCTION__ );
return false;
}
return $wp_scripts->set_translations( $handle, $domain, $path );
}
/**
* Remove a registered script.
*

View File

@ -893,6 +893,91 @@ function load_child_theme_textdomain( $domain, $path = false ) {
return load_theme_textdomain( $domain, $path );
}
/**
* Load the script translated strings.
*
* @see WP_Scripts::set_translations()
* @link https://core.trac.wordpress.org/ticket/45103
* @global WP_Scripts $wp_scripts The WP_Scripts object for printing scripts.
*
* @since 5.0.0
*
* @param string $handle Name of the script to register a translation domain to.
* @param string $domain The textdomain.
* @param string $path Optional. The full file path to the directory containing translation files.
*
* @return false|string False if the script textdomain could not be loaded, the translated strings
* in JSON encoding otherwise.
*/
function load_script_textdomain( $handle, $domain, $path = null ) {
global $wp_scripts;
$path = untrailingslashit( $path );
$locale = is_admin() ? get_locale() : get_user_locale();
// If a path was given and the handle file exists simply return it.
$file_base = $domain === 'default' ? $locale : $domain . '-' . $locale;
$handle_filename = $file_base . '-' . $handle . '.json';
if ( $path && file_exists( $path . '/' . $handle_filename ) ) {
return file_get_contents( $path . '/' . $handle_filename );
}
$obj = $wp_scripts->registered[ $handle ];
/** This filter is documented in wp-includes/class.wp-scripts.php */
$src = esc_url( apply_filters( 'script_loader_src', $obj->src, $handle ) );
$relative = false;
$languages_path = WP_LANG_DIR;
$src_url = wp_parse_url( $src );
$content_url = wp_parse_url( content_url() );
$site_url = wp_parse_url( site_url() );
// If the host is the same or it's a relative URL.
if (
strpos( $src_url['path'], $content_url['path'] ) === 0 &&
( ! isset( $src_url['host'] ) || $src_url['host'] !== $content_url['host'] )
) {
// Make the src relative the specific plugin or theme.
$relative = trim( substr( $src, strlen( $content_url['path'] ) ), '/' );
$relative = explode( '/', $relative );
$languages_path = WP_LANG_DIR . '/' . $relative[0];
$relative = array_slice( $relative, 2 );
$relative = implode( '/', $relative );
} elseif ( ! isset( $src_url['host'] ) || $src_url['host'] !== $site_url['host'] ) {
if ( ! isset( $site_url['path'] ) ) {
$relative = trim( $src_url['path'], '/' );
} elseif ( ( strpos( $src_url['path'], $site_url['path'] ) === 0 ) ) {
// Make the src relative to the WP root.
$relative = substr( $src, strlen( $site_url['path'] ) );
$relative = trim( $relative, '/' );
}
}
// If the source is not from WP.
if ( false === $relative ) {
return false;
}
// Translations are always based on the unminified filename.
if ( substr( $relative, -7 ) === '.min.js' ) {
$relative = substr( $relative, 0, -7 ) . '.js';
}
$md5_filename = $file_base . '-' . md5( $relative ) . '.json';
if ( $path && file_exists( $path . '/' . $md5_filename ) ) {
return file_get_contents( $path . '/' . $md5_filename );
}
if ( file_exists( $languages_path . '/' . $md5_filename ) ) {
return file_get_contents( $languages_path . '/' . $md5_filename );
}
return false;
}
/**
* Loads plugin and theme textdomains just-in-time.
*

View File

@ -13,7 +13,7 @@
*
* @global string $wp_version
*/
$wp_version = '5.1-alpha-44168';
$wp_version = '5.1-alpha-44169';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.