Make WordPress Core

Changeset 43859


Ignore:
Timestamp:
11/01/2018 01:50:59 PM (6 years ago)
Author:
herregroen
Message:

I18N: Improve JavaScript translation support.

Improves upon [43825] by adding unit tests to cover additional use-cases and changes loading translations to only occur when outputting the script to allow setting translations on dependencies.

Props atimmer, omarreiss, nerrad, swissspidy, ocean90.
Fixes #45103.

Location:
branches/5.0
Files:
3 added
5 edited
1 moved

Legend:

Unmodified
Added
Removed
  • branches/5.0/src/wp-includes/class-wp-dependency.php

    r41162 r43859  
    6969
    7070    /**
     71     * Translation textdomain set for this dependency.
     72     *
     73     * @since 5.0.0
     74     * @var string
     75     */
     76    public $textdomain;
     77
     78    /**
     79     * Translation path set for this dependency.
     80     *
     81     * @since 5.0.0
     82     * @var string
     83     */
     84    public $translations_path;
     85
     86    /**
    7187     * Setup dependencies.
    7288     *
     
    95111    }
    96112
     113    public function set_translations( $domain, $path = null ) {
     114        if ( !is_string($domain) )
     115            return false;
     116        $this->textdomain        = $domain;
     117        $this->translations_path = $path;
     118        return true;
     119    }
    97120}
  • branches/5.0/src/wp-includes/class.wp-scripts.php

    r43825 r43859  
    326326        }
    327327
     328        $translations = $this->print_translations( $handle, false );
     329        if ( $translations ) {
     330            $translations = sprintf( "<script type='text/javascript'>\n%s\n</script>\n", $translations );
     331        }
     332
    328333        if ( ! preg_match( '|^(https?:)?//|', $src ) && ! ( $this->content_url && 0 === strpos( $src, $this->content_url ) ) ) {
    329334            $src = $this->base_url . $src;
     
    339344            return true;
    340345
    341         $tag = "{$cond_before}{$before_handle}<script type='text/javascript' src='$src'></script>\n{$after_handle}{$cond_after}";
     346        $tag = "{$translations}{$cond_before}{$before_handle}<script type='text/javascript' src='$src'></script>\n{$after_handle}{$cond_after}";
    342347
    343348        /**
     
    479484
    480485    /**
    481      * Register a translation textdomain.
     486     * Sets a translation textdomain.
    482487     *
    483488     * @since 5.0.0
     
    494499        }
    495500
    496         $json_translations = load_script_textdomain( $handle, $domain, $path );
    497 
    498         if ( ! $json_translations ) {
    499             return false;
    500         }
    501 
    502501        /** @var \_WP_Dependency $obj */
    503502        $obj = $this->registered[ $handle ];
    504         $obj->deps[] = 'wp-i18n';
    505 
    506         return $this->add_inline_script(
    507             $handle,
    508             '(function( translations ){' .
    509                 'wp.i18n.setLocaleData( translations.locale_data, "' . $domain . '" );' .
    510             '})(' . $json_translations . ');',
    511             'before'
    512         );
     503
     504        if ( ! in_array( 'wp-i18n', $obj->deps, true ) ) {
     505            $obj->deps[] = 'wp-i18n';
     506        }
     507        return $obj->set_translations( $domain, $path );
     508    }
     509
     510    /**
     511     * Prints translations set for a specific handle.
     512     *
     513     * @since 5.0.0
     514     *
     515     * @param string $handle Name of the script to add the inline script to. Must be lowercase.
     516     * @param bool   $echo   Optional. Whether to echo the script instead of just returning it.
     517     *                       Default true.
     518     * @return string|false Script on success, false otherwise.
     519     */
     520    public function print_translations( $handle, $echo = true ) {
     521        if ( ! isset( $this->registered[ $handle ] ) || empty( $this->registered[ $handle ]->textdomain ) ) {
     522            return false;
     523        }
     524
     525        $domain = $this->registered[ $handle ]->textdomain;
     526        $path   = $this->registered[ $handle ]->translations_path;
     527
     528        $json_translations = load_script_textdomain( $handle, $domain, $path );
     529
     530        if ( ! $json_translations ) {
     531            return false;
     532        }
     533
     534        $output = '(function( translations ){' .
     535                      'wp.i18n.setLocaleData( translations.locale_data, "' . $domain . '" );' .
     536                  '})(' . $json_translations . ');';
     537
     538        if ( $echo ) {
     539            printf( "<script type='text/javascript'>\n%s\n</script>\n", $output );
     540        }
     541
     542        return $output;
    513543    }
    514544
  • branches/5.0/src/wp-includes/functions.wp-scripts.php

    r43827 r43859  
    194194
    195195/**
    196  * Register translated strings for a script.
     196 * Sets translated strings for a script.
    197197 *
    198198 * Works only if the script has already been added.
    199199 *
    200200 * @see WP_Scripts::set_translations()
    201  * @link https://core.trac.wordpress.org/ticket/45103
    202201 * @global WP_Scripts $wp_scripts The WP_Scripts object for printing scripts.
    203202 *
     
    215214        _wp_scripts_maybe_doing_it_wrong( __FUNCTION__ );
    216215        return false;
    217     }
    218 
    219     if ( ! wp_script_is( $handle, 'enqueued' ) ) {
    220         _doing_it_wrong( __FUNCTION__, __( 'Script translations may only be set if the script is enqueued.' ), '5.0.0' );
    221216    }
    222217
  • branches/5.0/src/wp-includes/l10n.php

    r43846 r43859  
    877877 * @global WP_Scripts $wp_scripts The WP_Scripts object for printing scripts.
    878878 *
     879 * @since 5.0.0
     880 *
    879881 * @param string $handle Name of the script to register a translation domain to.
    880882 * @param string $domain The textdomain.
     
    887889    global $wp_scripts;
    888890
     891    $path   = untrailingslashit( $path );
    889892    $locale = is_admin() ? get_locale() : get_user_locale();
    890893
    891894    // If a path was given and the handle file exists simply return it.
    892     $handle_filename = $domain . '-' . $locale . '-' . $handle . '.json';
     895    $file_base       = $domain === 'default' ? $locale : $domain . '-' . $locale;
     896    $handle_filename = $file_base . '-' . $handle . '.json';
    893897    if ( $path && file_exists( $path . '/' . $handle_filename ) ) {
    894898        return file_get_contents( $path . '/' . $handle_filename );
     
    909913    // If the host is the same or it's a relative URL.
    910914    if (
    911         strpos( $content_url['path'], $src_url['path'] ) === 0 &&
     915        strpos( $src_url['path'], $content_url['path'] ) === 0 &&
    912916        ( ! isset( $src_url['host'] ) || $src_url['host'] !== $content_url['host'] )
    913917    ) {
     
    926930        $relative = trim( $src_url['path'], '/' );
    927931    } else if (
    928         ( strpos( $site_url['path'], $src_url['path'] ) === 0 ) &&
     932        ( strpos( $src_url['path'], $site_url['path'] ) === 0 ) &&
    929933        ( ! isset( $src_url['host'] ) || $src_url['host'] !== $site_url['host'] )
    930934    ) {
     
    944948    }
    945949
    946     $md5_filename = $domain . '-' . $locale . '-' . md5( $relative ) . '.json';
     950    $md5_filename = $file_base . '-' . md5( $relative ) . '.json';
    947951    if ( $path && file_exists( $path . '/' . $md5_filename ) ) {
    948952        return file_get_contents( $path . '/' . $md5_filename );
  • branches/5.0/tests/phpunit/tests/dependencies/scripts.php

    r43828 r43859  
    771771     * @ticket 45103
    772772     */
    773     public function test_wp_set_script_translation() {
     773    public function test_wp_set_script_translations() {
     774        wp_register_script( 'wp-i18n', '/wp-includes/js/dist/wp-i18n.js', array(), null );
     775        wp_enqueue_script( 'test-example', '/wp-includes/js/script.js', array(), null );
     776        wp_set_script_translations( 'test-example', 'default',  DIR_TESTDATA . '/languages' );
     777
     778        $expected  = "<script type='text/javascript' src='/wp-includes/js/dist/wp-i18n.js'></script>";
     779        $expected .= "\n<script type='text/javascript'>\n(function( translations ){" .
     780                "wp.i18n.setLocaleData( translations.locale_data, \"default\" );" .
     781            "})(" . file_get_contents( DIR_TESTDATA . '/languages/en_US-813e104eb47e13dd4cc5af844c618754.json' ) . ");\n</script>\n";
     782        $expected .= "<script type='text/javascript' src='/wp-includes/js/script.js'></script>\n";
     783
     784        $this->assertEquals( $expected, get_echo( 'wp_print_scripts' ) );
     785    }
     786
     787    /**
     788     * @ticket 45103
     789     */
     790    public function test_wp_set_script_translations_for_plugin() {
     791        wp_register_script( 'wp-i18n', '/wp-includes/js/dist/wp-i18n.js', array(), null );
     792        wp_enqueue_script( 'plugin-example', '/wp-content/plugins/my-plugin/js/script.js', array(), null );
     793        wp_set_script_translations( 'plugin-example', 'internationalized-plugin',  DIR_TESTDATA . '/languages/plugins' );
     794
     795        $expected  = "<script type='text/javascript' src='/wp-includes/js/dist/wp-i18n.js'></script>";
     796        $expected .= "\n<script type='text/javascript'>\n(function( translations ){" .
     797                     "wp.i18n.setLocaleData( translations.locale_data, \"internationalized-plugin\" );" .
     798                     "})(" . file_get_contents( DIR_TESTDATA . '/languages/plugins/internationalized-plugin-en_US-2f86cb96a0233e7cb3b6f03ad573be0b.json' ) . ");\n</script>\n";
     799        $expected .= "<script type='text/javascript' src='/wp-content/plugins/my-plugin/js/script.js'></script>\n";
     800
     801        $this->assertEquals( $expected, get_echo( 'wp_print_scripts' ) );
     802    }
     803
     804    /**
     805     * @ticket 45103
     806     */
     807    public function test_wp_set_script_translations_for_theme() {
     808        wp_register_script( 'wp-i18n', '/wp-includes/js/dist/wp-i18n.js', array(), null );
     809        wp_enqueue_script( 'theme-example', '/wp-content/themes/my-theme/js/script.js', array(), null );
     810        wp_set_script_translations( 'theme-example', 'internationalized-theme',  DIR_TESTDATA . '/languages/themes' );
     811
     812        $expected  = "<script type='text/javascript' src='/wp-includes/js/dist/wp-i18n.js'></script>";
     813        $expected .= "\n<script type='text/javascript'>\n(function( translations ){" .
     814                     "wp.i18n.setLocaleData( translations.locale_data, \"internationalized-theme\" );" .
     815                     "})(" . file_get_contents( DIR_TESTDATA . '/languages/themes/internationalized-theme-en_US-2f86cb96a0233e7cb3b6f03ad573be0b.json' ) . ");\n</script>\n";
     816        $expected .= "<script type='text/javascript' src='/wp-content/themes/my-theme/js/script.js'></script>\n";
     817
     818        $this->assertEquals( $expected, get_echo( 'wp_print_scripts' ) );
     819    }
     820
     821    /**
     822     * @ticket 45103
     823     */
     824    public function test_wp_set_script_translations_with_handle_file() {
     825        wp_register_script( 'wp-i18n', '/wp-includes/js/dist/wp-i18n.js', array(), null );
     826        wp_enqueue_script( 'script-handle', '/wp-admin/js/script.js', array(), null );
     827        wp_set_script_translations( 'script-handle', 'admin',  DIR_TESTDATA . '/languages/' );
     828
     829        $expected  = "<script type='text/javascript' src='/wp-includes/js/dist/wp-i18n.js'></script>";
     830        $expected .= "\n<script type='text/javascript'>\n(function( translations ){" .
     831                     "wp.i18n.setLocaleData( translations.locale_data, \"admin\" );" .
     832                     "})(" . file_get_contents( DIR_TESTDATA . '/languages/admin-en_US-script-handle.json' ) . ");\n</script>\n";
     833        $expected .= "<script type='text/javascript' src='/wp-admin/js/script.js'></script>\n";
     834
     835        $this->assertEquals( $expected, get_echo( 'wp_print_scripts' ) );
     836    }
     837
     838    /**
     839     * @ticket 45103
     840     */
     841    public function test_wp_set_script_translations_i18n_dependency() {
     842        global $wp_scripts;
     843
    774844        wp_register_script( 'wp-i18n', '/wp-includes/js/dist/wp-i18n.js', array(), null );
    775845        wp_enqueue_script( 'test-example', '/wp-includes/js/script.js', array(), null );
    776846        wp_set_script_translations( 'test-example', 'default',  DIR_TESTDATA . '/languages/' );
    777847
     848        $script = $wp_scripts->registered[ 'test-example' ];
     849
     850        $this->assertContains( 'wp-i18n', $script->deps );
     851    }
     852
     853    /**
     854     * @ticket 45103
     855     */
     856    public function test_wp_set_script_translations_when_translation_file_does_not_exist() {
     857        wp_register_script( 'wp-i18n', '/wp-includes/js/dist/wp-i18n.js', array(), null );
     858        wp_enqueue_script( 'test-example', '/wp-admin/js/script.js', array(), null );
     859        wp_set_script_translations( 'test-example', 'admin',  DIR_TESTDATA . '/languages/' );
     860
     861        $expected  = "<script type='text/javascript' src='/wp-includes/js/dist/wp-i18n.js'></script>";
     862        $expected .= "\n<script type='text/javascript' src='/wp-admin/js/script.js'></script>\n";
     863
     864        $this->assertEquals( $expected, get_echo( 'wp_print_scripts' ) );
     865    }
     866
     867    /**
     868     * @ticket 45103
     869     */
     870    public function test_wp_set_script_translations_after_register() {
     871        wp_register_script( 'wp-i18n', '/wp-includes/js/dist/wp-i18n.js', array(), null );
     872        wp_register_script( 'test-example', '/wp-includes/js/script.js', array(), null );
     873        wp_set_script_translations( 'test-example', 'default',  DIR_TESTDATA . '/languages' );
     874
     875        wp_enqueue_script( 'test-example' );
     876
    778877        $expected  = "<script type='text/javascript' src='/wp-includes/js/dist/wp-i18n.js'></script>";
    779878        $expected .= "\n<script type='text/javascript'>\n(function( translations ){" .
    780                 "wp.i18n.setLocaleData( translations.locale_data, \"default\" );" .
    781             "})(" . file_get_contents( DIR_TESTDATA . '/languages/default-en_US-813e104eb47e13dd4cc5af844c618754.json') . ");\n</script>\n";
     879                     "wp.i18n.setLocaleData( translations.locale_data, \"default\" );" .
     880                     "})(" . file_get_contents( DIR_TESTDATA . '/languages/en_US-813e104eb47e13dd4cc5af844c618754.json' ) . ");\n</script>\n";
    782881        $expected .= "<script type='text/javascript' src='/wp-includes/js/script.js'></script>\n";
     882
     883        $this->assertEquals( $expected, get_echo( 'wp_print_scripts' ) );
     884    }
     885
     886    /**
     887     * @ticket 45103
     888     */
     889    public function test_wp_set_script_translations_dependency() {
     890        wp_register_script( 'wp-i18n', '/wp-includes/js/dist/wp-i18n.js', array(), null );
     891        wp_register_script( 'test-dependency', '/wp-includes/js/script.js', array(), null );
     892        wp_set_script_translations( 'test-dependency', 'default',  DIR_TESTDATA . '/languages' );
     893
     894        wp_enqueue_script( 'test-example', '/wp-includes/js/script2.js', array( 'test-dependency' ), null );
     895
     896        $expected  = "<script type='text/javascript' src='/wp-includes/js/dist/wp-i18n.js'></script>";
     897        $expected .= "\n<script type='text/javascript'>\n(function( translations ){" .
     898                     "wp.i18n.setLocaleData( translations.locale_data, \"default\" );" .
     899                     "})(" . file_get_contents( DIR_TESTDATA . '/languages/en_US-813e104eb47e13dd4cc5af844c618754.json' ) . ");\n</script>\n";
     900        $expected .= "<script type='text/javascript' src='/wp-includes/js/script.js'></script>\n";
     901        $expected .= "<script type='text/javascript' src='/wp-includes/js/script2.js'></script>\n";
    783902
    784903        $this->assertEquals( $expected, get_echo( 'wp_print_scripts' ) );
Note: See TracChangeset for help on using the changeset viewer.