Make WordPress Core

Ticket #15677: 15677.11.patch

File 15677.11.patch, 30.1 KB (added by ocean90, 9 years ago)

Don't set transients when WP_INSTALLING

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

     
    437437        if ( $wp_current_db_version < 26691 )
    438438                upgrade_380();
    439439
     440        if ( $wp_current_db_version < 29600 )
     441                upgrade_400();
     442
    440443        maybe_disable_link_manager();
    441444
    442445        maybe_disable_automattic_widgets();
     
    13041307                deactivate_plugins( array( 'mp6/mp6.php' ), true );
    13051308        }
    13061309}
     1310
    13071311/**
     1312 * Execute changes made in WordPress 4.0.0.
     1313 *
     1314 * @since 4.0.0
     1315 */
     1316function upgrade_400() {
     1317        global $wp_current_db_version;
     1318        if ( $wp_current_db_version < 29600 ) {
     1319                if ( ! is_multisite() && false === get_option( 'WPLANG' ) ) {
     1320                        if (
     1321                                defined( 'WPLANG' ) && ( '' !== WPLANG ) && ( 'en_US' !== WPLANG ) &&
     1322                                in_array( WPLANG, get_available_languages() ) ) {
     1323                                update_option( 'WPLANG', WPLANG );
     1324                        } else {
     1325                                update_option( 'WPLANG', '' );
     1326                        }
     1327                }
     1328        }
     1329}
     1330
     1331/**
    13081332 * Execute network level changes
    13091333 *
    13101334 * @since 3.0.0
     
    14191443 */
    14201444function maybe_create_table($table_name, $create_ddl) {
    14211445        global $wpdb;
    1422        
     1446
    14231447        $query = $wpdb->prepare( "SHOW TABLES LIKE %s", $wpdb->esc_like( $table_name ) );
    14241448
    14251449        if ( $wpdb->get_var( $query ) == $table_name ) {
     
    21922216        dbDelta( $ms_queries );
    21932217}
    21942218endif;
    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                $locale = get_locale();
     319                // Check if current locale is still installed. en_US will fail this test, but that's okay.
     320                if ( ! in_array( $locale, get_available_languages() ) ) {
     321                        $locale = '';
     322                }
     323
     324                echo '<div class="language-chooser">';
     325                wp_dropdown_languages( array(
     326                        'name'     => 'WPLANG',
     327                        'id'       => 'WPLANG',
     328                        'selected' => $locale,
     329                ) );
     330                echo '<span class="spinner"></span>';
     331                echo '</div>';
     332
     333                // Add note about deprecated WPLANG constant
     334                if ( defined( 'WPLANG' ) && ( '' !== WPLANG ) ) {
     335                        ?>
     336                        <p class="description">
     337                                <?php _e( '<strong>Note:</strong> Language does no longer persist on the <code>WPLANG</code> constant in your <code>wp-config.php</code> file. Feel free to remove it.' ); ?>
     338                        </p>
     339                        <?php
     340                }
     341                ?>
     342        </td>
     343</tr>
    323344</table>
    324345
    325346<?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                                // English is selected
     185                                unload_textdomain( 'default' );
     186                        } else {
     187                                wp_install_load_language( wp_unslash( $_POST['WPLANG'] ) );
     188                        }
     189                }
    166190        }
    167191
    168192        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

     
    2424 * @return string The locale of the blog or from the 'locale' hook.
    2525 */
    2626function get_locale() {
    27         global $locale;
     27        global $locale, $wp_local_package;
    2828
    2929        if ( isset( $locale ) ) {
    3030                /**
     
    3737                return apply_filters( 'locale', $locale );
    3838        }
    3939
    40         // WPLANG is defined in wp-config.
    41         if ( defined( 'WPLANG' ) )
     40        // WPLANG was defined in wp-config.
     41        if ( defined( 'WPLANG' ) ) {
    4242                $locale = WPLANG;
     43        }
    4344
     45        if ( isset( $wp_local_package ) ) {
     46                $locale = $wp_local_package;
     47        }
     48
    4449        // If multisite, check options.
    4550        if ( is_multisite() ) {
    4651                // Don't check blog option when installing.
    47                 if ( defined( 'WP_INSTALLING' ) || ( false === $ms_locale = get_option( 'WPLANG' ) ) )
    48                         $ms_locale = get_site_option('WPLANG');
     52                if ( defined( 'WP_INSTALLING' ) || ( false === $ms_locale = get_option( 'WPLANG' ) ) ) {
     53                        $ms_locale = get_site_option( 'WPLANG' );
     54                }
    4955
    50                 if ( $ms_locale !== false )
     56                if ( $ms_locale !== false ) {
    5157                        $locale = $ms_locale;
     58                }
    5259        } elseif ( ! defined( 'WP_INSTALLING' ) ) {
    5360                $db_locale = get_option( 'WPLANG' );
    54                 if ( $db_locale ) {
     61                if ( $db_locale !== false ) {
    5562                        $locale = $db_locale;
    5663                }
    5764        }
    5865
    59         if ( empty( $locale ) )
     66        if ( empty( $locale ) ) {
    6067                $locale = 'en_US';
     68        }
    6169
    6270        /** This filter is documented in wp-includes/l10n.php */
    6371        return apply_filters( 'locale', $locale );
     
    818826}
    819827
    820828/**
    821  * Language selector. More to come.
     829 * Language selector.
    822830 *
    823831 * @since 4.0.0
    824832 *
    825833 * @see get_available_languages()
     834 * @see wp_get_available_translations()
    826835 *
    827836 * @param array $args Optional arguments. Default empty array.
    828837 */
    829838function wp_dropdown_languages( $args = array() ) {
    830         if ( isset( $args['languages'] ) ) {
    831                 $languages = $args['languages'];
    832         } else {
    833                 $languages = get_available_languages();
     839        require_once( ABSPATH . 'wp-admin/includes/translation-install.php' );
     840
     841        $locales = get_available_languages();
     842        $translations = wp_get_available_translations();
     843
     844        /*
     845         * get_available_languages() just returns the locales. Find the locale in
     846         * $translations to get the native name. Fall back to locale.
     847         */
     848        $languages = array();
     849        foreach ( $locales as $locale ) {
     850                if ( isset( $translations[ $locale ] ) ) {
     851                        $translation = $translations[ $locale ];
     852                        $languages[ $locale ] = array(
     853                                'language'    => $translation['language'],
     854                                'native_name' => $translation['native_name'],
     855                        );
     856                } else {
     857                        $languages[ $locale ] = array(
     858                                'language'    => $locale,
     859                                'native_name' => $locale,
     860                        );
     861                }
    834862        }
    835863
     864        // Remove installed languages from available translations.
     865        $translations = array_diff_key( $translations, $languages );
     866
    836867        printf( '<select name="%s" id="%s">', esc_attr( $args['name'] ), esc_attr( $args['id'] ) );
    837         echo '<option value="">en_US</option>';
     868
     869        $structure = array();
     870
     871        // List installed languages.
     872        $structure[] = '<optgroup label="' . esc_attr_x( 'Installed', 'translations' ) . '">';
     873        $structure[] = '<option value="" data-installed="1">English (United States)</option>';
    838874        foreach ( $languages as $language ) {
    839                 $selected = selected( $language, $args['selected'], false );
    840                 echo '<option value="' . esc_attr( $language ) .'"' . $selected . '>' . $language . '</option>';
     875                $selected = selected( $language['language'], $args['selected'], false );
     876                $structure[] = '<option value="' . esc_attr( $language['language'] ) .'"' . $selected . ' data-installed="1">' . esc_html( $language['native_name'] ) . '</option>';
    841877        }
     878        $structure[] = '</optgroup>';
     879
     880        // List available translations.
     881        if ( ! empty( $translations ) && ( ! is_multisite() || is_super_admin() ) && ( ! defined( 'DISALLOW_FILE_MODS' ) || ! DISALLOW_FILE_MODS ) ) {
     882                $structure[] = '<optgroup label="' . esc_attr_x( 'Available', 'translations' ) . '">';
     883                foreach ( $translations as $translation ) {
     884                        $selected = selected( $translation['language'], $args['selected'], false );
     885                        $structure[] = '<option value="' . esc_attr( $translation['language'] ) .'"' . $selected . '>' . esc_html( $translation['native_name'] ) . '</option>';
     886                }
     887                $structure[] = '</optgroup>';
     888        }
     889
     890        echo join( "\n", $structure );
     891
    842892        echo '</select>';
    843893}
  • src/wp-includes/load.php

     
    776776        $locales = $locations = array();
    777777
    778778        while ( true ) {
    779                 if ( defined( 'WPLANG' ) ) {
    780                         if ( '' == WPLANG )
    781                                 break;
    782                         $locales[] = WPLANG;
    783                 }
    784 
    785779                if ( isset( $wp_local_package ) )
    786780                        $locales[] = $wp_local_package;
    787781
  • src/wp-includes/version.php

     
    1111 *
    1212 * @global int $wp_db_version
    1313 */
    14 $wp_db_version = 29188;
     14$wp_db_version = 29600;
    1515
    1616/**
    1717 * Holds the TinyMCE version
  • wp-config-sample.php

     
    6262$table_prefix  = 'wp_';
    6363
    6464/**
    65  * WordPress Localized Language, defaults to English.
    66  *
    67  * Change this to localize WordPress. A corresponding MO file for the chosen
    68  * language must be installed to wp-content/languages. For example, install
    69  * de_DE.mo to wp-content/languages and set WPLANG to 'de_DE' to enable German
    70  * language support.
    71  */
    72 define('WPLANG', '');
    73 
    74 /**
    7565 * For developers: WordPress debugging mode.
    7666 *
    7767 * Change this to true to enable the display of notices during development.