Skip to:
Content

BuddyPress.org

Ticket #4857: 4857.03.patch

File 4857.03.patch, 15.1 KB (added by DJPaul, 12 years ago)
  • new file p-core/admin/bp-core-translations.php

    diff --git a/bp-core/admin/bp-core-translations.php b/bp-core/admin/bp-core-translations.php
    new file mode 100644
    index 0000000..e5fb94c
    - +  
     1<?php
     2/**
     3 * Handles automatic download of translations
     4 *
     5 * @package BuddyPress
     6 * @subpackage CoreAdministration
     7 * @since BuddyPress (1.8)
     8 */
     9
     10// Exit if accessed directly
     11if ( ! defined( 'ABSPATH' ) ) exit;
     12
     13/**
     14 * Creates an instance of the BP_Translate class that downloads translations for BuddyPress automatically
     15 *
     16 * @since BuddyPress (1.8)
     17 */
     18function bp_automatic_translations() {
     19        if ( ! current_user_can( 'update_plugins' ) )
     20                return;
     21
     22        if ( ! is_admin() || ( is_multisite() && ! is_network_admin() ) )
     23                return;
     24
     25        // Store a reference to the BP_Translate object in the BP global for other plugins
     26        buddypress()->translate = BP_Translate::get_instance();
     27}
     28add_action( 'bp_admin_init', 'bp_automatic_translations' );
     29
     30/**
     31 * If we're in the WordPress dashboard, and a pending translation is available, bump the update count.
     32 *
     33 * This has to be hooked before admin_init due to wp_get_update_data() being invoked in wp-admin/menu.php before the admin_init action is called.
     34 *
     35 * @since BuddyPress (1.8)
     36 */
     37function bp_admin_maybe_bump_update_count() {
     38        if ( ! current_user_can( 'update_plugins' ) )
     39                return;
     40
     41        if ( ! is_admin() || ( is_multisite() && ! is_network_admin() ) )
     42                return;
     43
     44        add_filter( 'wp_get_update_data', array( 'BP_Translate', 'maybe_bump_update_count' ) );
     45}
     46add_action( 'bp_init', 'bp_admin_maybe_bump_update_count' );
     47
     48/**
     49 * Fetch translations from http://translate.wordpress.org/ and display an update prompt on the admin dashboard.
     50 *
     51 * @since BuddyPress (1.8)
     52 */
     53class BP_Translate {
     54
     55        /**
     56         * Singleton instance of the BP_Translate class
     57         *
     58         * @since BuddyPress (1.8)
     59         * @var BP_Translate
     60         */
     61        private static $instance;
     62
     63        /**
     64         * Return the singleton instance of the BP_Translate class
     65         *
     66         * @return BP_Translate
     67         * @since BuddyPress (1.8)
     68         */
     69        static public function get_instance() {
     70                if ( ! self::$instance )
     71                        self::$instance = new BP_Translate;
     72
     73                return self::$instance;
     74        }
     75
     76        /**
     77         * Constructor
     78         *
     79         * @since BuddyPress (1.8)
     80         */
     81        public function __construct() {
     82                $this->register_actions();
     83                $this->register_cron();     // Intentionally after actions
     84        }
     85
     86        /**
     87         * Hook into actions necessary to automate the translation process and customise wp-admin
     88         *
     89         * @since BuddyPress (1.8)
     90         */
     91        protected function register_actions() {
     92                add_action( 'bp_translate_update_check',                           array( __CLASS__, 'check_for_updated_translation' ) );
     93                add_action( 'core_upgrade_preamble',                               array( __CLASS__, 'updates_screen' ) );
     94                add_action( 'update-core-custom_do-update-buddypress-translation', array( __CLASS__, 'updates_screen_iframe' ) );
     95                add_action( 'update-custom_update-buddypress-translation',         array( __CLASS__, 'update_translation' ) );
     96        }
     97
     98        /**
     99         * Register cron task to check for language updates
     100         *
     101         * @since BuddyPress (1.8)
     102         */
     103        protected function register_cron() {
     104                if ( ! wp_next_scheduled( 'bp_translate_update_check' ) )
     105                        wp_schedule_event( time(), 'daily', 'bp_translate_update_check' );
     106        }
     107
     108        /**
     109         * Find out if there's a newer translation available for this site on translate.wordpress.org
     110         *
     111         * @since BuddyPress (1.8)
     112         */
     113        static public function check_for_updated_translation() {
     114                $locale = BP_Translate::get_locale();
     115                if ( 'en_US' === $locale )
     116                        return;
     117
     118                // No point checking if we know there's an updated translation
     119                if ( bp_is_translation_update_pending() )
     120                        return;
     121
     122                $locale = BP_Translate::get_glotpress_locale();
     123                if ( ! $locale )
     124                        return;
     125
     126                $url  = 'https://translate.wordpress.org/projects/buddypress/%1$s/%2$s/default/export-translations?format=mo';
     127                $args = bp_get_translation_version() ? array( 'headers' => 'If-Modified-Since: ' . gmdate( 'D, d M Y H:i:s', bp_get_translation_version() ) . ' GMT' ) : array();
     128
     129                // Check version of translation on translate.wordpress.org
     130                $response = wp_remote_head( sprintf( $url, buddypress()->glotpress_version, $locale ), $args );
     131                if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) === 304 || wp_remote_retrieve_response_code( $response ) !== 200 )
     132                        return;
     133
     134                // An updated translation is available
     135                bp_update_option( '_bp_translation_pending', true );
     136        }
     137
     138        /**
     139         * Get the current locale
     140         *
     141         * @return string
     142         * @since BuddyPress (1.8)
     143         */
     144        static public function get_locale() {
     145                return apply_filters( 'buddypress_locale', get_locale() );
     146        }
     147
     148        /**
     149         * Get the GlotPress locale code for the current locale
     150         *
     151         * @return string|bool Returns bool if an error occured, otherwise the GlotPress locale as a string
     152         * @since BuddyPress (1.8)
     153         */
     154        static public function get_glotpress_locale() {
     155                static $glotpress_locale;
     156                if ( ! empty( $glotpress_locale ) )
     157                        return $glotpress_locale;
     158
     159                // Get the list of available translations from translate.wordpress.org
     160                $translations = wp_remote_get( sprintf( 'https://translate.wordpress.org/api/projects/buddypress/%1$s', buddypress()->glotpress_version ) );
     161                if ( is_wp_error( $translations ) || wp_remote_retrieve_response_code( $translations ) !== 200 )
     162                        return false;
     163
     164                $translations = json_decode( wp_remote_retrieve_body( $translations ) );
     165                if ( is_null( $translations ) )
     166                        return false;
     167
     168                // Does the requested $locale have an available translation?
     169                $translations = array_shift( wp_list_filter( $translations->translation_sets, array( 'wp_locale' => BP_Translate::get_locale() ) ) );
     170                if ( empty( $translations ) )
     171                        return false;
     172
     173                $glotpress_locale = $translations->locale;
     174                return $glotpress_locale;
     175        }
     176
     177        /**
     178         * If in the WordPress dashboard, maybe bump the "available updates" count if there's a pending translation.
     179         *
     180         * @param array $data Counts and UI strings for available updates
     181         * @return array
     182         * @since BuddyPress (1.8)
     183         */
     184        static public function maybe_bump_update_count( $data ) {
     185                if ( current_user_can( 'update_plugins' ) && bp_is_translation_update_pending() )
     186                        $data['counts']['total']++;
     187
     188                return $data;
     189        }
     190
     191        /**
     192         * If we have a pending translation, display a message on the wp-admin/update-core.php screen.
     193         *
     194         * @since BuddyPress (1.8)
     195         */
     196        static public function updates_screen() {
     197
     198                if ( BP_Translate::get_locale() === 'en_US' || ! bp_is_translation_update_pending() )
     199                        return;
     200        ?>
     201                <h3><?php _e( 'BuddyPress Translation', 'buddypress' ); ?></h3>
     202                <p><?php _e( 'An updated version of the current BuddyPress translation is available. Click &#8220;Update Translation&#8221;.', 'buddypress' ); ?></p>
     203
     204                <form method="post" action="<?php echo esc_url( 'update-core.php?action=do-update-buddypress-translation' ); ?>" name="update-buddypress-translation" class="upgrade">
     205                        <?php wp_nonce_field( 'update-buddypress-translation' ); ?>
     206
     207                        <p><input class="button" type="submit" value="<?php esc_attr_e( 'Update Translation', 'buddypress' ); ?>" name="upgrade" /></p>
     208                </form>
     209        <?php
     210        }
     211
     212        /**
     213         * We're going to update the BuddyPress translation; output an iframe in which the magic will happen.
     214         *
     215         * This copies the implementation for the Plugin and Theme updates wherein the work is done in a separate
     216         * request that is iframed in. This allows WordPress to recover from any errors during the process.
     217         *
     218         * @since BuddyPress (1.8)
     219         */
     220        static public function updates_screen_iframe() {
     221
     222                if ( ! current_user_can( 'update_plugins' ) )
     223                        wp_die( __( 'You do not have sufficient permissions to update this site.', 'buddypress' ) );
     224
     225                check_admin_referer( 'update-buddypress-translation' );
     226
     227                // If no pending translation updates, redirect away.
     228                if ( ! bp_is_translation_update_pending() ) {
     229                        wp_redirect( admin_url('update-core.php') );
     230                        exit;
     231                }
     232
     233                require_once( ABSPATH . 'wp-admin/admin-header.php' );
     234                $title = __( 'Update BuddyPress Translation', 'buddypress' );
     235                $url   = wp_nonce_url( 'update.php?action=update-buddypress-translation', 'update-buddypress-translation' );
     236
     237                echo '<div class="wrap">';
     238                screen_icon( 'plugins' );
     239                echo '<h2>' . esc_html( $title ) . '</h2>';
     240                echo '<iframe src=' . esc_url( $url ) . ' style="width: 100%; height: 100%; min-height: 750px;" frameborder="0"></iframe>';
     241                echo '</div>';
     242
     243                include( ABSPATH . 'wp-admin/admin-footer.php' );
     244        }
     245
     246        /**
     247         * Download the latest version of the current locale's translation from translate.wordpress.org
     248         *
     249         * @since BuddyPress (1.8)
     250         */
     251        static public function update_translation() {
     252
     253                // @todo Not sure if this does anything
     254                if ( ! defined( 'IFRAME_REQUEST' ) )
     255                        define( 'IFRAME_REQUEST', true );
     256
     257                if ( ! current_user_can( 'update_plugins' ) || BP_Translate::get_locale() === 'en_US' )
     258                        wp_die( __( 'You do not have sufficient permissions to update this site.', 'buddypress' ) );
     259
     260                check_admin_referer( 'update-buddypress-translation' );
     261                iframe_header();
     262
     263                echo '<p>'  . __( 'The update process is starting. This process may take a while on some hosts, so please be patient.', 'buddypress' ) . '</p>';
     264                echo '<h4>' . __( 'Updating BuddyPress Translation', 'buddypress' ) . '</h4>';
     265
     266                // Download the .mo to a local temporary file
     267                $url = 'https://translate.wordpress.org/projects/buddypress/%1$s/%2$s/default/export-translations?format=mo';
     268                $tmp = download_url( sprintf( $url, buddypress()->glotpress_version, BP_Translate::get_glotpress_locale() ) );
     269
     270                if ( is_wp_error( $tmp ) ) {
     271                        $css_class = 'error';
     272                        $message   = __( 'Error: failure updating translation.', 'buddypress' );
     273                        $message  .= '</p><p><strong>' . $tmp->get_error_message() . '</strong>';
     274
     275                } else {
     276                        $css_class  = 'updated';
     277                        $message    = __( 'Translation updated succesfully!', 'buddypress' );
     278                        $upload_dir = wp_upload_dir();
     279                        $new_file   = sprintf( '%s/buddypress/buddypress-%s.mo', $upload_dir['basedir'], BP_Translate::get_locale() );
     280
     281                        // Check the target folder exists
     282                        @mkdir( $upload_dir['basedir'] . '/buddypress' );
     283
     284                        // Move the file into place
     285                        @copy( $tmp, $new_file );
     286                        @unlink( $tmp );
     287
     288                        // Store the current timestamp for future checks, for the IF-MODIFIED-SINCE header
     289                        bp_update_option( '_bp_translation_version', time() );
     290
     291                        // Clear the pending translation flag
     292                        bp_delete_option( '_bp_translation_pending' );
     293                }
     294        ?>
     295
     296        <div class="<?php echo esc_attr( $css_class ); ?>">
     297                <p><?php echo $message; ?></p>
     298        </div>
     299
     300        <p><a href="<?php echo self_admin_url( 'update-core.php' ); ?>" target="_parent"><?php _e( 'Return to WordPress Updates', 'buddypress' ); ?></a></p>
     301
     302        <?php
     303                iframe_footer();
     304        }
     305}
  • bp-core/bp-core-admin.php

    diff --git a/bp-core/bp-core-admin.php b/bp-core/bp-core-admin.php
    index 3943c7c..427a283 100644
    a b class BP_Admin { 
    9393         * @access private
    9494         */
    9595        private function includes() {
    96                 require( $this->admin_dir . 'bp-core-actions.php'    );
    97                 require( $this->admin_dir . 'bp-core-settings.php'   );
    98                 require( $this->admin_dir . 'bp-core-functions.php'  );
    99                 require( $this->admin_dir . 'bp-core-components.php' );
    100                 require( $this->admin_dir . 'bp-core-slugs.php'      );
     96                require( $this->admin_dir . 'bp-core-actions.php'      );
     97                require( $this->admin_dir . 'bp-core-settings.php'     );
     98                require( $this->admin_dir . 'bp-core-functions.php'    );
     99                require( $this->admin_dir . 'bp-core-components.php'   );
     100                require( $this->admin_dir . 'bp-core-slugs.php'        );
     101                require( $this->admin_dir . 'bp-core-translations.php' );
    101102        }
    102103
    103104        /**
  • bp-core/bp-core-functions.php

    diff --git a/bp-core/bp-core-functions.php b/bp-core/bp-core-functions.php
    index 3d3e02e..ee6fc0d 100644
    a b add_action( 'wp_footer', 'bp_core_print_generation_time' ); 
    748748 * @package BuddyPress Core
    749749 */
    750750function bp_core_load_buddypress_textdomain() {
    751         $locale        = apply_filters( 'buddypress_locale', get_locale() );
    752         $mofile        = sprintf( 'buddypress-%s.mo', $locale );
    753         $mofile_global = WP_LANG_DIR . '/' . $mofile;
    754         $mofile_local  = BP_PLUGIN_DIR . 'bp-languages/' . $mofile;
    755 
    756         if ( file_exists( $mofile_global ) )
    757                 return load_textdomain( 'buddypress', $mofile_global );
    758         elseif ( file_exists( $mofile_local ) )
    759                 return load_textdomain( 'buddypress', $mofile_local );
    760         else
    761                 return false;
     751        $locale      = apply_filters( 'buddypress_locale', get_locale() );
     752        $mofile      = sprintf( 'buddypress-%s.mo', $locale );
     753        $uploads_dir = wp_upload_dir();
     754
     755        $translation_paths = array(
     756                WP_LANG_DIR . "/{$mofile}",
     757                BP_PLUGIN_DIR . "bp-languages/{$mofile}",
     758                $uploads_dir['basedir'] . "/buddypress/{$mofile}",
     759        );
     760
     761        foreach ( $translation_paths as $path ) {
     762                if ( file_exists( $path ) )
     763                        return load_textdomain( 'buddypress', $path );
     764        }
    762765}
    763 add_action ( 'bp_core_loaded', 'bp_core_load_buddypress_textdomain' );
     766add_action( 'bp_core_loaded', 'bp_core_load_buddypress_textdomain' );
    764767
    765768/**
    766769 * Initializes {@link BP_Embed} after everything is loaded.
  • bp-core/bp-core-options.php

    diff --git a/bp-core/bp-core-options.php b/bp-core/bp-core-options.php
    index 550e885..36c98c7 100644
    a b function bp_get_default_options() { 
    6464                // The ID for the current theme package.
    6565                '_bp_theme_package_id'            => 'legacy',
    6666
     67                // Timestamp of the the current translation from translate.wordpress.org
     68                '_bp_translation_version'         => 0,
     69
     70                // Is there a more recent translation available on translate.wordpress.org?
     71                '_bp_translation_pending'         => false,
     72
    6773                /** Groups ************************************************************/
    6874
    6975                // @todo Move this into the groups component
    function bp_is_akismet_active( $default = true ) { 
    536542function bp_get_theme_package_id( $default = 'legacy' ) {
    537543        return apply_filters( 'bp_get_theme_package_id', bp_get_option( '_bp_theme_package_id', $default ) );
    538544}
     545
     546/**
     547 * Get the timestamp of the the current translation from translate.wordpress.org
     548 *
     549 * @param int $default Optional; default value 0.
     550 * @return int Unix timestamp
     551 * @since BuddyPress (1.8)
     552 */
     553function bp_get_translation_version( $default = 0 ) {
     554        return apply_filters( 'bp_get_translation_version', (int) bp_get_option( '_bp_translation_version', $default ) );
     555}
     556
     557/**
     558 * Does translate.wordpress.org have a more recent translation available on translate.wordpress.org?
     559 *
     560 * @param bool $default Optional; defaults to false.
     561 * @return bool
     562 * @see BP_Translate->check_for_updated_translation()
     563 * @since BuddyPress (1.8)
     564 */
     565function bp_is_translation_update_pending( $default = false ) {
     566        return apply_filters( 'bp_is_translation_update_pending', (bool) bp_get_option( '_bp_translation_pending', $default ) );
     567}
  • bp-loader.php

    diff --git a/bp-loader.php b/bp-loader.php
    index 550846f..bd337c5 100644
    a b class BuddyPress { 
    280280
    281281                $this->version    = '1.8-bleeding-7013';
    282282                $this->db_version = 6080;
     283                $this->glotpress_version = 'dev';
    283284
    284285                /** Loading ***********************************************************/
    285286