WordPress.org

Make WordPress Core

Ticket #15677: 15677.6.patch

File 15677.6.patch, 26.4 KB (added by ocean90, 6 years ago)

Adds language chooser to network settings too

  • src/wp-admin/css/forms.css

     
    761761        margin: -3px 3px;
    762762}
    763763
     764.settings-php .language-chooser .spinner,
     765.options-general-php .language-chooser .spinner {
     766        float: none;
     767        margin: 0 3px;
     768        vertical-align: middle;
     769}
     770
    764771/* =Media Queries
    765772-------------------------------------------------------------- */
    766773
     
    988995                width: 49%;
    989996        }
    990997}
    991 
  • src/wp-admin/includes/translation-install.php

     
     1<?php
     2/**
     3 * WordPress Translation Install Administration API
     4 *
     5 * @package WordPress
     6 * @subpackage Administration
     7 */
     8
     9
     10/**
     11 * Retrieve translations from WordPress Plugins API.
     12 *
     13 * @since 4.0.0
     14 *
     15 * @param string       $type Type of translations. Accepts 'plugins', 'themes', 'core'.
     16 * @param array|object $args Translation API arguments. Optional.
     17 *
     18 * @return object|WP_Error On success an object of translations, WP_Error on failure.
     19 */
     20function translations_api( $type, $args = null ) {
     21        include( ABSPATH . WPINC . '/version.php' ); // include an unmodified $wp_version
     22
     23        if ( ! in_array( $type, array( 'plugins', 'themes', 'core' ) ) ) {
     24                return  new WP_Error( 'invalid_type', __( 'Invalid translation type.' ) );
     25        }
     26
     27        /**
     28         * Allows a plugin to override the WordPress.org Translation Install API entirely.
     29         *
     30         * @since 4.0.0
     31         *
     32         * @param bool|array  $result The result object. Default false.
     33         * @param string      $type   The type of translations being requested.
     34         * @param object      $args   Translation API arguments.
     35         */
     36        $res = apply_filters( 'translations_api', false, $type, $args );
     37
     38        if ( false === $res ) {
     39                $url = $http_url = 'http://api.wordpress.org/translations/' . $type . '/1.0/';
     40                if ( $ssl = wp_http_supports( array( 'ssl' ) ) ) {
     41                        $url = set_url_scheme( $url, 'https' );
     42                }
     43
     44                $options = array(
     45                        'timeout' => 3,
     46                        'body' => array(
     47                                'wp_version' => $wp_version,
     48                                'locale'     => get_locale(),
     49                                'version'    => $args['version'], // Version of plugin, theme or core
     50                        ),
     51                );
     52
     53                if ( 'core' !== $type ) {
     54                        $options['body']['slug'] = $args['slug']; // plugin or theme slug
     55                }
     56
     57                $request = wp_remote_post( $url, $options );
     58
     59                if ( $ssl && is_wp_error( $request ) ) {
     60                        trigger_error( __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.' ) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ), headers_sent() || WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE );
     61
     62                        $request = wp_remote_post( $http_url, $options );
     63                }
     64
     65                if ( is_wp_error( $request ) ) {
     66                        $res = new WP_Error( 'translations_api_failed', __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.' ), $request->get_error_message() );
     67                } else {
     68                        $res = json_decode( wp_remote_retrieve_body( $request ), true );
     69                        if ( ! is_object( $res ) && ! is_array( $res ) ) {
     70                                $res = new WP_Error( 'translations_api_failed', __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.' ), wp_remote_retrieve_body( $request ) );
     71                        }
     72                }
     73        }
     74
     75        /**
     76         * Filter the Translation Install API response results.
     77         *
     78         * @since 4.0.0
     79         *
     80         * @param object|WP_Error $res  Response object or WP_Error.
     81         * @param string          $type The type of translations being requested.
     82         * @param object          $args Translation API arguments.
     83         */
     84        return apply_filters( 'translations_api_result', $res, $type, $args );
     85}
     86
     87/**
     88 * Get available translations from the WordPress.org API.
     89 *
     90 * @since 4.0.0
     91 *
     92 * @return array Array of translations, each an array of data.
     93 */
     94function wp_get_available_translations() {
     95        if ( false !== ( $translations = get_site_transient( 'available_translations' ) ) ) {
     96                return $translations;
     97        }
     98
     99        include( ABSPATH . WPINC . '/version.php' ); // include an unmodified $wp_version
     100
     101        $api = translations_api( 'core', array( 'version' => $wp_version ) );
     102
     103        if ( is_wp_error( $api ) || empty( $api['translations'] ) ) {
     104                return array();
     105        }
     106
     107        $translations = array();
     108        // Key the array with the language code for now
     109        foreach ( $api['translations'] as $translation ) {
     110                $translations[ $translation['language'] ] = $translation;
     111        }
     112
     113        set_site_transient( 'available_translations', $translations, 3 * HOUR_IN_SECONDS );
     114
     115        return $translations;
     116}
     117
     118/**
     119 * Output the input fields for the language selection form on the installation screen.
     120 *
     121 * @since 4.0.0
     122 *
     123 * @see wp_get_available_translations()
     124 *
     125 * @param array $languages Array of available languages (populated via the Translations API).
     126 */
     127function wp_install_language_form( $languages ) {
     128        $installed_languages = get_available_languages();
     129
     130        echo "<label class='screen-reader-text' for='language'>Select a default language</label>\n";
     131        echo "<select size='14' name='language' id='language'>\n";
     132        echo '<option value="" lang="en" selected="selected" data-continue="Continue" data-installed="1">English (United States)</option>';
     133        echo "\n";
     134
     135        if ( defined( 'WPLANG' ) && ( '' !== WPLANG ) && ( 'en_US' !== WPLANG ) ) {
     136                if ( isset( $languages[ WPLANG ] ) ) {
     137                        $language = $languages[ WPLANG ];
     138                        echo '<option value="' . esc_attr( $language['language'] ) . '" lang="' . esc_attr( $language['iso'][1] ) . '">' . esc_html( $language['native_name'] ) . "</option>\n";
     139                        unset( $languages[ WPLANG ] );
     140                }
     141        }
     142
     143        foreach ( $languages as $language ) {
     144                printf( '<option value="%s" lang="%s" data-continue="%s"%s>%s</option>' . "\n",
     145                        esc_attr( $language['language'] ),
     146                        esc_attr( $language['iso'][1] ),
     147                        esc_attr( $language['strings']['continue'] ),
     148                        in_array( $language['language'], $installed_languages ) ? ' data-installed="1"' : '',
     149                        esc_html( $language['native_name'] ) );
     150        }
     151        echo "</select>\n";
     152        echo '<p class="step"><span class="spinner"></span><input id="language-continue" type="submit" class="button button-primary button-large" value="Continue" /></p>';
     153}
     154
     155/**
     156 * Download a language pack.
     157 *
     158 * @since 4.0.0
     159 *
     160 * @see wp_get_available_translations()
     161 *
     162 * @param string $download Language code to download.
     163 * @return string|bool Returns the language code if successfully downloaded
     164 *                     (or already installed), or false on failure.
     165 */
     166function wp_install_download_language_pack( $download ) {
     167        // Check if the translation is already installed.
     168        if ( in_array( $download, get_available_languages() ) ) {
     169                return $download;
     170        }
     171
     172        if ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS ) {
     173                return false;
     174        }
     175
     176        // Confirm the translation is one we can download.
     177        $translations = wp_get_available_translations();
     178        if ( ! $translations ) {
     179                return false;
     180        }
     181        foreach ( $translations as $translation ) {
     182                if ( $translation['language'] === $download ) {
     183                        $translation_to_load = true;
     184                        break;
     185                }
     186        }
     187
     188        if ( empty( $translation_to_load ) ) {
     189                return false;
     190        }
     191        $translation = (object) $translation;
     192
     193        require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
     194        $skin = new Automatic_Upgrader_Skin;
     195        $upgrader = new Language_Pack_Upgrader( $skin );
     196        $translation->type = 'core';
     197        /**
     198         * @todo failures (such as non-direct FS)
     199         */
     200        $upgrader->upgrade( $translation, array( 'clear_update_cache' => false ) );
     201        return $translation->language;
     202}
     203
     204/**
     205 * Load a translation during the install process.
     206 *
     207 * @since 4.0.0
     208 *
     209 * @see load_textdomain()
     210 *
     211 * @param string $translation Translation to load.
     212 * @return string|bool Returns the language code if successfully loaded,
     213 *                     or false on failure.
     214 */
     215function wp_install_load_language( $translation ) {
     216        if ( ! empty( $translation ) ) {
     217                if ( in_array( $translation, get_available_languages() ) ) {
     218                        $translation_to_load = $translation;
     219                }
     220        }
     221
     222        if ( empty( $translation_to_load ) ) {
     223                return false;
     224        }
     225
     226        unload_textdomain( 'default' ); // Start over.
     227        load_textdomain( 'default', WP_LANG_DIR . "/{$translation_to_load}.mo" );
     228        load_textdomain( 'default', WP_LANG_DIR . "/admin-{$translation_to_load}.mo" );
     229        return $translation_to_load;
     230}
  • src/wp-admin/includes/upgrade.php

     
    14191419 */
    14201420function maybe_create_table($table_name, $create_ddl) {
    14211421        global $wpdb;
    1422        
     1422
    14231423        $query = $wpdb->prepare( "SHOW TABLES LIKE %s", $wpdb->esc_like( $table_name ) );
    14241424
    14251425        if ( $wpdb->get_var( $query ) == $table_name ) {
     
    21922192        dbDelta( $ms_queries );
    21932193}
    21942194endif;
    2195 
    2196 /**
    2197  * Output the input fields for the language selection form on the installation screen.
    2198  *
    2199  * @since 4.0.0
    2200  *
    2201  * @see wp_get_available_translations_from_api()
    2202  *
    2203  * @param array $languages Array of available languages (populated via the Translations API).
    2204  */
    2205 function wp_install_language_form( $languages ) {
    2206         $installed_languages = get_available_languages();
    2207 
    2208         echo "<label class='screen-reader-text' for='language'>Select a default language</label>\n";
    2209         echo "<select size='14' name='language' id='language'>\n";
    2210         echo '<option value="" lang="en" selected="selected" data-continue="Continue" data-installed="1">English (United States)</option>';
    2211         echo "\n";
    2212 
    2213         if ( defined( 'WPLANG' ) && ( '' !== WPLANG ) && ( 'en_US' !== WPLANG ) ) {
    2214                 if ( isset( $languages[ WPLANG ] ) ) {
    2215                         $language = $languages[ WPLANG ];
    2216                         echo '<option value="' . esc_attr( $language['language'] ) . '" lang="' . esc_attr( $language['iso'][1] ) . '">' . esc_html( $language['native_name'] ) . "</option>\n";
    2217                 }
    2218         }
    2219 
    2220         foreach ( $languages as $language ) {
    2221                 printf( '<option value="%s" lang="%s" data-continue="%s"%s>%s</option>' . "\n",
    2222                         esc_attr( $language['language'] ),
    2223                         esc_attr( $language['iso'][1] ),
    2224                         esc_attr( $language['strings']['continue'] ),
    2225                         in_array( $language['language'], $installed_languages ) ? ' data-installed="1"' : '',
    2226                         esc_html( $language['native_name'] ) );
    2227         }
    2228         echo "</select>\n";
    2229         echo '<p class="step"><span class="spinner"></span><input id="language-continue" type="submit" class="button button-primary button-large" value="Continue" /></p>';
    2230 }
    2231 
    2232 /**
    2233  * Get available translations from the WordPress.org API.
    2234  *
    2235  * @since 4.0.0
    2236  *
    2237  * @see wp_remote_post()
    2238  *
    2239  * @return array Array of translations, each an array of data.
    2240  */
    2241 function wp_get_available_translations_from_api() {
    2242         $url = 'http://api.wordpress.org/translations/core/1.0/';
    2243         if ( wp_http_supports( array( 'ssl' ) ) ) {
    2244                 $url = set_url_scheme( $url, 'https' );
    2245         }
    2246 
    2247         $options = array(
    2248                 'timeout' => 3,
    2249                 'body' => array( 'version' => $GLOBALS['wp_version'] ),
    2250         );
    2251 
    2252         $response = wp_remote_post( $url, $options );
    2253         $body = wp_remote_retrieve_body( $response );
    2254         if ( $body && $body = json_decode( $body, true ) ) {
    2255                 $translations = array();
    2256                 // Key the array with the language code for now
    2257                 foreach ( $body['translations'] as $translation ) {
    2258                         $translations[ $translation['language'] ] = $translation;
    2259                 }
    2260                 return $translations;
    2261         }
    2262         return false;
    2263 }
    2264 
    2265 /**
    2266  * Download a language pack.
    2267  *
    2268  * @since 4.0.0
    2269  *
    2270  * @see wp_get_available_translations_from_api()
    2271  *
    2272  * @param string $download Language code to download.
    2273  * @return string|bool Returns the language code if successfully downloaded
    2274  *                     (or already installed), or false on failure.
    2275  */
    2276 function wp_install_download_language_pack( $download ) {
    2277         // Check if the translation is already installed.
    2278         if ( in_array( $download, get_available_languages() ) ) {
    2279                 return $download;
    2280         }
    2281 
    2282         // Confirm the translation is one we can download.
    2283         $translations = wp_get_available_translations_from_api();
    2284         if ( ! $translations ) {
    2285                 return false;
    2286         }
    2287         foreach ( $translations as $translation ) {
    2288                 if ( $translation['language'] === $download ) {
    2289                         $translation_to_load = true;
    2290                         break;
    2291                 }
    2292         }
    2293 
    2294         if ( empty( $translation_to_load ) ) {
    2295                 return false;
    2296         }
    2297         $translation = (object) $translation;
    2298 
    2299         require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
    2300         $skin = new Automatic_Upgrader_Skin;
    2301         $upgrader = new Language_Pack_Upgrader( $skin );
    2302         $translation->type = 'core';
    2303         /**
    2304          * @todo failures (such as non-direct FS)
    2305          */
    2306         $upgrader->upgrade( $translation, array( 'clear_update_cache' => false ) );
    2307         return $translation->language;
    2308 }
    2309 
    2310 /**
    2311  * Load a translation during the install process.
    2312  *
    2313  * @since 4.0.0
    2314  *
    2315  * @see load_textdomain()
    2316  *
    2317  * @param string $translation Translation to load.
    2318  * @return string|bool Returns the language code if successfully loaded,
    2319  *                     or false on failure.
    2320  */
    2321 function wp_install_load_language( $translation ) {
    2322         if ( ! empty( $translation ) ) {
    2323                 if ( in_array( $translation, get_available_languages() ) ) {
    2324                         $translation_to_load = $translation;
    2325                 }
    2326         }
    2327 
    2328         if ( empty( $translation_to_load ) ) {
    2329                 return false;
    2330         }
    2331 
    2332         unload_textdomain( 'default' ); // Start over.
    2333         load_textdomain( 'default', WP_LANG_DIR . "/{$translation_to_load}.mo" );
    2334         load_textdomain( 'default', WP_LANG_DIR . "/admin-{$translation_to_load}.mo" );
    2335         return $translation_to_load;
    2336 }
  • src/wp-admin/install.php

     
    3838/** Load WordPress Administration Upgrade API */
    3939require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
    4040
     41/** Load WordPress Translation Install API */
     42require_once( ABSPATH . 'wp-admin/includes/translation-install.php' );
     43
    4144/** Load wpdb */
    4245require_once( ABSPATH . WPINC . '/wp-db.php' );
    4346
     
    179182switch($step) {
    180183        case 0: // Step 0
    181184
    182                 if ( empty( $_GET['language'] ) && ( $languages = wp_get_available_translations_from_api() ) ) {
     185                if ( empty( $_GET['language'] ) && ( $languages = wp_get_available_translations() ) ) {
    183186                        display_header( 'language-chooser' );
    184187                        echo '<form id="setup" method="post" action="?step=1">';
    185188                        wp_install_language_form( $languages );
  • src/wp-admin/network/settings.php

     
    1919$title = __( 'Network Settings' );
    2020$parent_file = 'settings.php';
    2121
     22/**
     23 * Display JavaScript on the page.
     24 *
     25 * @since 4.0.0
     26 */
     27function network_settings_add_js() {
     28?>
     29<script type="text/javascript">
     30jQuery(document).ready( function($) {
     31        var languageSelect = $( '#WPLANG' );
     32        $( 'form' ).submit( function() {
     33                // Don't show a spinner for English and installed languages,
     34                // as there is nothing to download.
     35                if ( ! languageSelect.find( 'option:selected' ).data( 'installed' ) ) {
     36                        $( this ).find( '.language-chooser .spinner' ).css( 'display', 'inline-block' );
     37                }
     38        });
     39});
     40</script>
     41<?php
     42}
     43add_action( 'admin_head', 'network_settings_add_js' );
     44
    2245get_current_screen()->add_help_tab( array(
    2346                'id'      => 'overview',
    2447                'title'   => __('Overview'),
     
    5881                'illegal_names', 'limited_email_domains', 'banned_email_domains', 'WPLANG', 'admin_email',
    5982        );
    6083
     84        // Handle translation install
     85        if ( ! empty( $_POST['WPLANG'] ) && ( ! defined( 'DISALLOW_FILE_MODS' ) || ! DISALLOW_FILE_MODS ) ) {
     86                require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
     87                require_once( ABSPATH . 'wp-admin/includes/translation-install.php' );
     88
     89                $language = wp_install_download_language_pack( wp_unslash( $_POST['WPLANG'] ) );
     90                if ( $language ) {
     91                        $_POST['WPLANG'] = $language;
     92                }
     93        }
     94
    6195        foreach ( $options as $option_name ) {
    6296                if ( ! isset($_POST[$option_name]) )
    6397                        continue;
     
    102136                                        <input name="admin_email" type="email" id="admin_email" class="regular-text" value="<?php echo esc_attr( get_site_option( 'admin_email' ) ) ?>" />
    103137                                        <p class="description">
    104138                                                <?php _e( 'This email address will receive notifications. Registration and support emails will also come from this address.' ); ?>
    105                                         </p>   
     139                                        </p>
    106140                                </td>
    107141                        </tr>
    108142                </table>
     
    165199<?php echo esc_textarea( $limited_email_domains == '' ? '' : implode( "\n", (array) $limited_email_domains ) ); ?></textarea>
    166200                                        <p class="description">
    167201                                                <?php _e( 'If you want to limit site registrations to certain domains. One domain per line.' ) ?>
    168                                         </p>   
     202                                        </p>
    169203                                </td>
    170204                        </tr>
    171205
     
    231265<?php echo esc_textarea( get_site_option( 'first_comment' ) ) ?></textarea>
    232266                                        <p class="description">
    233267                                                <?php _e( 'The first comment on a new site.' ) ?>
    234                                         </p>   
     268                                        </p>
    235269                                </td>
    236270                        </tr>
    237271                        <tr>
     
    273307                        </tr>
    274308                </table>
    275309
    276 <?php
    277                 $languages = get_available_languages();
    278                 if ( ! empty( $languages ) ) {
    279                         $lang = get_site_option( 'WPLANG' );
    280 ?>
    281310                <h3><?php _e( 'Language Settings' ); ?></h3>
    282311                <table class="form-table">
    283                                 <tr>
    284                                         <th><label for="WPLANG"><?php _e( 'Default Language' ); ?></label></th>
    285                                         <td>
    286                                                 <select name="WPLANG" id="WPLANG">
    287                                                         <?php mu_dropdown_languages( $languages, get_site_option( 'WPLANG' ) ); ?>
    288                                                 </select>
    289                                         </td>
    290                                 </tr>
     312                        <tr>
     313                                <th><label for="WPLANG"><?php _e( 'Default Language' ); ?></label></th>
     314                                <td>
     315                                        <?php
     316                                        $lang = get_site_option( 'WPLANG' );
     317                                        if ( ! in_array( $lang, get_available_languages() ) ) {
     318                                                $lang = '';
     319                                        }
     320
     321                                        echo '<div class="language-chooser">';
     322                                        wp_dropdown_languages( array(
     323                                                'name'     => 'WPLANG',
     324                                                'id'       => 'WPLANG',
     325                                                'selected' => $lang,
     326                                        ) );
     327                                        echo '<span class="spinner"></span>';
     328                                        echo '</div>';
     329                                        ?>
     330                                </td>
     331                        </tr>
    291332                </table>
    292 <?php
    293                 } // languages
    294 ?>
    295333
    296334                <h3><?php _e( 'Menu Settings' ); ?></h3>
    297335                <table id="menu" class="form-table">
     
    324362                        </tr>
    325363                </table>
    326364
    327                 <?php 
     365                <?php
    328366                /**
    329367                 * Fires at the end of the Network Settings form, before the submit button.
    330368                 *
  • src/wp-admin/options-general.php

     
    5050                                        date : format.val()
    5151                                }, function(d) { format.siblings('.spinner').hide(); format.siblings('.example').text(d); } );
    5252                });
     53
     54                var languageSelect = $( '#WPLANG' );
     55                $( 'form' ).submit( function() {
     56                        // Don't show a spinner for English and installed languages,
     57                        // as there is nothing to download.
     58                        if ( ! languageSelect.find( 'option:selected' ).data( 'installed' ) ) {
     59                                $( this ).find( '.language-chooser .spinner' ).css( 'display', 'inline-block' );
     60                        }
     61                });
    5362        });
    5463//]]>
    5564</script>
     
    302311</select></td>
    303312</tr>
    304313<?php do_settings_fields('general', 'default'); ?>
    305 <?php
    306         $languages = get_available_languages();
    307         if ( $languages ) :
    308 ?>
    309         <tr>
    310                 <th width="33%" scope="row"><label for="WPLANG"><?php _e('Site Language') ?></label></th>
    311                 <td>
    312                         <?php wp_dropdown_languages( array(
    313                                 'name'      => 'WPLANG',
    314                                 'id'        => 'WPLANG',
    315                                 'selected'  => get_option( 'WPLANG' ),
    316                                 'languages' => $languages,
    317                         ) ); ?>
    318                 </td>
    319         </tr>
    320 <?php
    321         endif;
    322 ?>
     314<tr>
     315        <th width="33%" scope="row"><label for="WPLANG"><?php _e( 'Site Language' ); ?></label></th>
     316        <td>
     317                <?php
     318                // TODO: Better handling of WPLANG constant, get_site_option('WPLANG'), maybe use get_locale() instead?
     319                $lang = get_option( 'WPLANG' );
     320                if ( ! in_array( $lang, get_available_languages() ) ) {
     321                        $lang = '';
     322                }
     323
     324                echo '<div class="language-chooser">';
     325                wp_dropdown_languages( array(
     326                        'name'     => 'WPLANG',
     327                        'id'       => 'WPLANG',
     328                        'selected' => $lang,
     329                ) );
     330                echo '<span class="spinner"></span>';
     331                echo '</div>';
     332
     333                if ( empty( $lang ) && ! is_multisite() && defined( 'WPLANG' ) && ( '' !== WPLANG ) && ( 'en_US' !== WPLANG ) ) {
     334                        ?>
     335                        <p class="description">
     336                                <?php
     337                                printf(
     338                                        __( 'In your <code>wp-config.php</code> file <code>WPLANG</code> is defined as %s.' ),
     339                                        '<code>' . esc_html( WPLANG ) . '</code>'
     340                                );
     341                                ?>
     342                        </p>
     343                        <?php
     344                }
     345                ?>
     346        </td>
     347</tr>
    323348</table>
    324349
    325350<?php do_settings_sections('general'); ?>
  • src/wp-admin/options.php

     
    151151                $options = $whitelist_options[ $option_page ];
    152152        }
    153153
    154         // Handle custom date/time formats
    155154        if ( 'general' == $option_page ) {
     155                // Handle custom date/time formats
    156156                if ( !empty($_POST['date_format']) && isset($_POST['date_format_custom']) && '\c\u\s\t\o\m' == wp_unslash( $_POST['date_format'] ) )
    157157                        $_POST['date_format'] = $_POST['date_format_custom'];
    158158                if ( !empty($_POST['time_format']) && isset($_POST['time_format_custom']) && '\c\u\s\t\o\m' == wp_unslash( $_POST['time_format'] ) )
     
    163163                        $_POST['gmt_offset'] = preg_replace('/UTC\+?/', '', $_POST['gmt_offset']);
    164164                        $_POST['timezone_string'] = '';
    165165                }
     166
     167                // Handle translation install
     168                if ( isset( $_POST['WPLANG'] ) ) {
     169                        require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
     170                        require_once( ABSPATH . 'wp-admin/includes/translation-install.php' );
     171
     172                        if ( ! empty( $_POST['WPLANG'] ) &&
     173                                ( ! is_multisite() || is_super_admin() ) &&
     174                                ( ! defined( 'DISALLOW_FILE_MODS' ) || ! DISALLOW_FILE_MODS )
     175                        ) {
     176                                $language = wp_install_download_language_pack( wp_unslash( $_POST['WPLANG'] ) );
     177                                if ( $language ) {
     178                                        $_POST['WPLANG'] = $language;
     179                                }
     180                        }
     181
     182                        // Load new language to translate "Settings saved" message
     183                        if ( '' === $_POST['WPLANG'] ) {
     184                                if ( ! is_multisite() && defined( 'WPLANG' ) && ( '' !== WPLANG ) && ( 'en_US' !== WPLANG ) ) {
     185                                        wp_install_load_language( WPLANG );
     186                                } else {
     187                                        unload_textdomain( 'default' );
     188                                }
     189                        } else {
     190                                wp_install_load_language( wp_unslash( $_POST['WPLANG'] ) );
     191                        }
     192                }
    166193        }
    167194
    168195        if ( $options ) {
  • src/wp-admin/setup-config.php

     
    3232
    3333require( ABSPATH . 'wp-settings.php' );
    3434
    35 require( ABSPATH . 'wp-admin/includes/upgrade.php' );
     35/** Load WordPress Administration Upgrade API */
     36require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
    3637
     38/** Load WordPress Translation Install API */
     39require_once( ABSPATH . 'wp-admin/includes/translation-install.php' );
     40
    3741// Support wp-config-sample.php one level up, for the develop repo.
    3842if ( file_exists( ABSPATH . 'wp-config-sample.php' ) )
    3943        $config_file = file( ABSPATH . 'wp-config-sample.php' );
     
    8690switch($step) {
    8791        case -1:
    8892
    89                 if ( empty( $_GET['language'] ) && ( $languages = wp_get_available_translations_from_api() ) ) {
     93                if ( empty( $_GET['language'] ) && ( $languages = wp_get_available_translations() ) ) {
    9094                        setup_config_display_header( 'language-chooser' );
    9195                        echo '<form id="setup" method="post" action="?step=0">';
    9296                        wp_install_language_form( $languages );
  • src/wp-includes/l10n.php

     
    823823 * @since 4.0.0
    824824 *
    825825 * @see get_available_languages()
     826 * @see wp_get_available_translations()
    826827 *
    827828 * @param array $args Optional arguments. Default empty array.
    828829 */
    829830function wp_dropdown_languages( $args = array() ) {
    830         if ( isset( $args['languages'] ) ) {
    831                 $languages = $args['languages'];
    832         } else {
    833                 $languages = get_available_languages();
     831        require_once( ABSPATH . 'wp-admin/includes/translation-install.php' );
     832
     833        $locales = get_available_languages();
     834        $translations = wp_get_available_translations();
     835
     836        /*
     837         * get_available_languages() just returns the locales. Find the locale in
     838         * $translations to get the native name.
     839         */
     840        $languages = array();
     841        foreach ( $locales as $locale ) {
     842                if ( isset( $translations[ $locale ] ) ) {
     843                        $translation = $translations[ $locale ];
     844                        $languages[ $locale ] = array(
     845                                'language'     => $translation['language'],
     846                                'native_name'  => $translation['native_name'],
     847                        );
     848                } else {
     849                        $languages[ $locale ] = array(
     850                                'language'     => $locale,
     851                                'native_name'  => $locale,
     852                        );
     853                }
    834854        }
    835855
     856        // Remove installed languages from available translations
     857        $translations = array_diff_key( $translations, $languages );
     858
    836859        printf( '<select name="%s" id="%s">', esc_attr( $args['name'] ), esc_attr( $args['id'] ) );
    837         echo '<option value="">en_US</option>';
     860
     861        $structure = array();
     862
     863        // Installed languages
     864        $structure[] = '<optgroup label="' . esc_attr_x( 'Installed', 'translations' ) . '">';
     865        $structure[] = '<option value="" data-installed="1">English (United States)</option>';
    838866        foreach ( $languages as $language ) {
    839                 $selected = selected( $language, $args['selected'], false );
    840                 echo '<option value="' . esc_attr( $language ) .'"' . $selected . '>' . $language . '</option>';
     867                $selected = selected( $language['language'], $args['selected'], false );
     868                $structure[] = '<option value="' . esc_attr( $language['language'] ) .'"' . $selected . ' data-installed="1">' . esc_html( $language['native_name'] ) . '</option>';
    841869        }
     870        $structure[] = '</optgroup>';
     871
     872        // Available translations
     873        if ( ! empty( $translations ) && ( ! is_multisite() || is_super_admin() ) && ( ! defined( 'DISALLOW_FILE_MODS' ) || ! DISALLOW_FILE_MODS ) ) {
     874                $structure[] = '<optgroup label="' . esc_attr_x( 'Available', 'translations' ) . '">';
     875                foreach ( $translations as $translation ) {
     876                        $selected = selected( $translation['language'], $args['selected'], false );
     877                        $structure[] = '<option value="' . esc_attr( $translation['language'] ) .'"' . $selected . '>' . esc_html( $translation['native_name'] ) . '</option>';
     878                }
     879                $structure[] = '</optgroup>';
     880        }
     881
     882        echo join( "\n", $structure );
     883
    842884        echo '</select>';
    843885}