WordPress.org

Making WordPress.org

Ticket #340: 340.5.diff

File 340.5.diff, 18.3 KB (added by iandunn, 7 years ago)

Minor fixes

  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wp-i18n-teams/css/front-end.css

     
     1/*
     2 * Table of all locales
     3 */
     4
     5.i18n-label.latest {
     6        color: #468847;
     7}
     8.i18n-label.minor-behind {
     9        color: #F7D708;
     10}
     11.i18n-label.major-behind-one {
     12        color: #E6A45A;
     13}
     14.i18n-label.major-behind-many {
     15        color: #e38587;
     16}
     17
     18.locale-version.latest {
     19        background: #d2e7ca;
     20}
     21.locale-version.minor-behind {
     22        background: #fef0c1;
     23}
     24.locale-version.major-behind-one {
     25        background: #E6A45A;
     26}
     27.locale-version.major-behind-many {
     28        background: #e38587;
     29}
     30
     31
     32/*
     33 * Details page for an individual locale
     34 */
     35
     36#locale-header {
     37        padding: 0 20px 20px 20px;
     38        background-color: #F5F5F5;
     39        border: 1px solid #E3E3E3;
     40        border-radius: 4px;
     41        box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.05) inset;
     42}
     43#locale-header ul,
     44#main ul#postlist .postcontent #locale-header ul {
     45        overflow: auto;
     46        margin-left: 0 !important; /* !important is necessary here to override P2's use of !important in .postcontent ul */
     47}
     48#locale-header ul li {
     49        list-style-type: none;
     50}
     51#locale-header ul#locale-details {
     52        margin-bottom: 0 !important; /* !important is necessary here to override P2's use of !important in .postcontent ul */
     53}
     54#locale-download {
     55        margin-bottom: 0 !important; /* !important is necessary here to override P2's use of !important in .postcontent ul */
     56}
     57#locale-header ul li.download-button,
     58#main ul#postlist .postcontent #locale-header ul li.download-button {
     59        float: left;
     60        height: 34px;
     61        margin: 8px 12px 0 0;   /* todo put list spacing on the button itself, so that the ul takes up no space when there are no li's inside it */
     62        padding: 6px 12px;
     63}
     64#locale-header ul li.download-button a {
     65        font-size: 1.1em;
     66        color: white;
     67}
     68#locale-details,
     69#main ul#locale-details {
     70        font-size: 1.2em;
     71}
     72
     73.validators,
     74#main ul#postlist .postcontent ul.validators {
     75        overflow: auto;
     76        margin: 0 !important; /* !important is necessary here to override P2's use of !important in .postcontent ul */
     77        padding: 0;
     78}
     79.validators li {
     80        float: left;
     81        width: 280px;           /* todo use flexbox to prog enhance this so that they fill the space. AF is good one to test */
     82        padding-bottom: 15px;
     83        list-style-type: none;
     84}
     85.validators .gravatar {
     86        position: relative;
     87        top: -6px;
     88        float: left;
     89        margin: 0 10px 10px 0;
     90        padding: 2px;
     91}
     92.validators a {
     93        display: block;
     94        margin: 6px 0 2px;
     95        font-size: 16px;
     96        text-decoration: none;
     97}
     98
     99.translators-info table {
     100        width: 100%;
     101        margin: .7em 0 1.5em;
     102        border: 1px solid #ccc;
     103        border-width: 1px 1px 1px 0;
     104        border-spacing: 0;
     105}
     106.translators-info th {
     107        background: #ccc;
     108        border: 1px solid #ccc;
     109        border-width: 1px 0 0 1px;
     110        padding: 6px 15px;
     111}
     112.translators-info td {
     113        border: 1px solid #ccc;
     114        border-width: 1px 0 0 1px;
     115        padding: 6px 15px;
     116}
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wp-i18n-teams/views/all-locales.php

     
     1<?php if ( $locale_data ) : ?>
     2
     3        <div class="translators-info">
     4                <p>
     5                        <?php printf(
     6                                __( '%s locales up-to-date. %s locales behind by one minor version. %s locales behind by one major version. %s locales behind by two or more major versions. %s locales do not yet have a package available.', 'wporg' ),
     7                                '<strong class="i18n-label latest">' . $locale_data['status_counts']['latest'] . '</strong>',
     8                                '<strong class="i18n-label minor-behind">' . $locale_data['status_counts']['minor-behind'] . '</strong>',
     9                                '<strong class="i18n-label major-behind-one">' . $locale_data['status_counts']['major-behind-one'] . '</strong>',
     10                                '<strong class="i18n-label major-behind-many">' . $locale_data['status_counts']['major-behind-many'] . '</strong>',
     11                                '<strong class="i18n-label no-site no-releases">' . ( $locale_data['status_counts']['no-site'] + $locale_data['status_counts']['no-releases'] ) . '</strong>'
     12                        ); ?>
     13                </p>
     14
     15                <table>
     16                        <thead>
     17                                <tr>
     18                                        <th><?php _e( 'Locale Name',      'wporg' ); ?></th>
     19                                        <th><?php _e( 'Native Name',      'wporg' ); ?></th>
     20                                        <th><?php _e( 'Locale Code',      'wporg' ); ?></th>
     21                                        <th><?php _e( 'WordPress Locale', 'wporg' ); ?></th>
     22                                        <th><?php _e( 'Version',          'wporg' ); ?></th>
     23                                        <th><!-- intentionally blank --></th>
     24                                </tr>
     25                        </thead>
     26
     27                        <tbody>
     28                                <?php foreach ( $locales as $locale ) : ?>
     29                                        <tr class="locale-version <?php echo esc_attr( $locale_data[ $locale->wp_locale ]['status'] ); ?>">
     30                                                <td><?php echo esc_html( $locale->english_name ); ?></td>
     31                                                <td><?php echo esc_html( $locale->native_name ); ?></td>
     32
     33                                                <td>
     34                                                        <?php if ( $locale_data[ $locale->wp_locale ]['rosetta_site_url'] ) : ?>
     35                                                                <a href="<?php echo esc_url( $locale_data[ $locale->wp_locale ]['rosetta_site_url'] ); ?>">
     36                                                                        <?php echo esc_html( $locale->slug ); ?>
     37                                                                </a>
     38                                                        <?php else : ?>
     39                                                                <?php echo esc_html( $locale->slug ); ?>
     40                                                        <?php endif; ?>
     41                                                </td>
     42
     43                                                <td><?php echo esc_html( $locale->wp_locale ); ?></td>
     44
     45                                                <td>
     46                                                        <?php
     47                                                                if ( $locale_data[ $locale->wp_locale ]['rosetta_site_url'] ) {
     48                                                                        if ( $locale_data[ $locale->wp_locale ]['latest_release'] ) {
     49                                                                                echo esc_html( $locale_data[ $locale->wp_locale ]['latest_release'] );
     50                                                                        } else {
     51                                                                                _e( 'None', 'wporg' );
     52                                                                        }
     53                                                                } else {
     54                                                                        _e( 'No site', 'wporg' );
     55                                                                }
     56                                                        ?>
     57                                                </td>
     58
     59                                                <td>
     60                                                        <a href="<?php echo esc_url( add_query_arg( 'locale', $locale->wp_locale ) ); ?>">
     61                                                                <?php _e( 'More', 'wporg' ); ?>
     62                                                        </a>
     63                                                </td>
     64                                        </tr>
     65                                <?php endforeach; ?>
     66                        </tbody>
     67                </table>
     68        </div> <!-- /.translators-info -->
     69
     70<?php else : ?>
     71
     72        <p class="alert alert-info" role="alert">
     73                <?php _e( 'Localization data is not available.', 'wporg' ); ?>
     74        </p>
     75
     76<?php endif; ?>
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wp-i18n-teams/views/locale-details.php

     
     1<?php if ( $locale_data && is_a( $locale, 'GP_Locale' ) ) : ?>
     2        <?php $locale_data = $locale_data[ $locale->wp_locale ]; ?>
     3
     4        <div id="locale-header">
     5                <h1>
     6                        <?php echo esc_html( $locale->native_name ); ?>
     7
     8                        <?php if ( $locale->native_name != $locale->english_name ) : ?>
     9                                / <?php echo esc_html( $locale->english_name ); ?>
     10                        <?php endif; ?>
     11                </h1>
     12
     13                <ul id="locale-details">
     14                        <li>
     15                                <strong><?php _e( 'Locale site:', 'wporg' ); ?></strong>
     16                                <a href="<?php echo esc_url( $locale_data['rosetta_site_url'] ); ?>"><?php _e( 'View locale site', 'wporg' ); ?></a>
     17                        </li>
     18
     19                        <li>
     20                                <strong><?php _e( 'Version:', 'wporg' ); ?></strong>
     21                                <?php echo $locale_data['latest_release'] ? esc_html( $locale_data['latest_release'] ) : __( 'None available', 'wporg' ); ?>
     22                        </li>
     23
     24                        <li>
     25                                <strong><?php _e( 'WordPress Locale:', 'wporg' ); ?></strong>
     26                                <?php echo esc_html( $locale->wp_locale ); ?>
     27                        </li>
     28                </ul>
     29
     30                <?php if ( $locale_data['localized_core_url'] ) : ?>
     31                        <ul id="locale-download">
     32                                <li class="button download-button">
     33                                        <a href="<?php echo esc_url( $locale_data['localized_core_url'] ); ?>" role="button">
     34                                                <?php printf( __( 'Download WordPress in %s', 'wporg' ), $locale->native_name ); ?>
     35                                        </a>
     36                                </li>
     37
     38                                <?php if ( $locale_data['language_pack_url'] ) : ?>
     39                                        <li class="button download-button">
     40                                                <a href="<?php echo esc_url( $locale_data['language_pack_url'] ); ?>" role="button">
     41                                                        <?php // translators: %s is the latest version ?>
     42                                                        <?php printf( __( 'Download language pack (%s)', 'wporg' ), $locale_data['latest_release'] ); ?>
     43                                                </a>
     44                                        </li>
     45                                <?php endif; ?>
     46                        </ul>
     47                <?php endif;  ?>
     48        </div>
     49
     50
     51        <h2>Validators</h2>
     52
     53        <?php if ( empty( $locale_data['validators'] ) ) : ?>
     54                <p><?php printf( __( '%s does not have any validators yet.', 'wporg' ), $locale->native_name ); ?></p>
     55        <?php else : ?>
     56                <ul class="validators">
     57                        <?php foreach ( $locale_data['validators'] as $validator ) : ?>
     58                                <li>
     59                                        <a href="https://profiles.wordpress.org/<?php echo esc_attr( $validator[2] ); ?>">
     60                                                <img src="https://secure.gravatar.com/avatar/<?php echo esc_attr( $validator[1] ); ?>?size=60" class="gravatar" alt="<?php echo esc_attr( $validator[0] ); ?>" />
     61                                                <?php echo esc_html( $validator[0] ); ?>
     62                                        </a>
     63                                </li>
     64                        <?php endforeach; ?>
     65                </ul>
     66        <?php endif; ?>
     67
     68
     69        <h2>Translators</h2>
     70
     71        <?php if ( empty( $locale_data['translators'] ) ) : ?>
     72                <p><?php printf( __( '%s does not have any translators yet.', 'wporg' ), $locale->native_name ); ?></p>
     73        <?php else : ?>
     74                <ul>
     75                        <?php foreach ( $locale_data['translators'] as $username => $name ) : ?>
     76                                <li>
     77                                        <a href="https://profiles.wordpress.org/<?php echo esc_attr( $username ); ?>">
     78                                                <?php echo esc_html( $name ); ?>
     79                                        </a>
     80                                </li>
     81                        <?php endforeach; ?>
     82                </ul>
     83        <?php endif; ?>
     84
     85        <p class="alert alert-info" role="alert">
     86                <a href="https://translate.wordpress.org/languages/<?php echo esc_attr( $locale->slug ); ?>">
     87                        <?php printf( __( 'Become a translator yourself, check if %s needs some help!', 'wporg' ), $locale->native_name ); ?>
     88                </a>
     89        </p>
     90
     91<?php else : ?>
     92
     93        <p class="alert alert-info" role="alert">
     94                <?php _e( 'Localization data is not available.', 'wporg' ); ?>
     95        </p>
     96
     97<?php endif; ?>
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/wp-i18n-teams/wp-i18n-teams.php

     
     1<?php
     2/*
     3Plugin Name: WP I18N Teams
     4Description: Provides shortcodes for displaying details about translation teams.
     5Version:     0.9
     6License:     GPLv2 or later
     7Author:      Marko Heijnen
     8Author URI:  http://www.markoheijnen.com
     9Text Domain: wporg
     10*/
     11
     12
     13/*
     14 * TODO
     15 *
     16 * inline TODOs
     17 * cross browser testing
     18 * fix cron bug
     19 * final review + double check security
     20 *
     21 * ask nacin for a sanity check on cache_locale_data() and get_contributors()
     22 * deploy new API_WPORG_PATH constant and wp4.css (including header cachebuster) changes before deploying this
     23 */
     24
     25
     26class WP_I18n_Teams {
     27        const LOCALE_DATA_TRANSIENT_KEY = 'wit_locale_data';
     28
     29        /**
     30         * Constructor
     31         */
     32        public function __construct() {
     33                add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ) );
     34                add_filter( 'cron_schedules',     array( $this, 'add_cron_intervals' ) );
     35                add_action( 'wit_refresh_cache',  array( $this, 'cache_locale_data' ) );       // todo this runs when visiting wp-cron directly, but not when by visiting pages
     36
     37                add_shortcode( 'wp-locales',      array( $this, 'wp_locales' ) );
     38
     39                $this->activate(); // todo shouldn't need this once cron bug is fixed
     40        }
     41
     42        /**
     43         * Prepares site to use the plugin during activation
     44         */
     45        public function activate() {
     46                if ( false === wp_next_scheduled( 'wit_refresh_cache' ) ) {
     47                        wp_schedule_event( time(), 'wit_five_minutes', 'wit_refresh_cache' );
     48                }
     49        }
     50
     51        /**
     52         * Rolls back activation procedures when de-activating the plugin
     53         */
     54        public function deactivate() {
     55                wp_clear_scheduled_hook( 'wit_refresh_cache' );
     56        }
     57
     58        /**
     59         * Enqueue JavaScript and CSS
     60         */
     61        public function enqueue_assets() {
     62                wp_enqueue_style( 'wp-i18n-teams', plugins_url( 'css/front-end.css', __FILE__ ), array(), 1 );
     63        }
     64
     65        /**
     66         * Adds custom intervals to the cron schedule.
     67         *
     68         * @param array $schedules
     69         *
     70         * @return array
     71         */
     72        public function add_cron_intervals( $schedules ) {
     73                $schedules[ 'wit_five_minutes' ] = array(
     74                        'interval' => 5 * MINUTE_IN_SECONDS,
     75                        'display'  => 'Every 5 minutes'
     76                );
     77
     78                return $schedules;
     79        }
     80
     81        /**
     82         * Render the [wp-locales] shortcode.
     83         *
     84         * @param array $attributes
     85         *
     86         * @return string
     87         */
     88        public function wp_locales( $attributes ) {
     89                //do_action( 'wit_refresh_cache' ); // todo
     90                // delete_transient( self::LOCALE_DATA_TRANSIENT_KEY ); // todo
     91
     92                $locale_data = get_transient( self::LOCALE_DATA_TRANSIENT_KEY );
     93
     94                ob_start();
     95
     96                if ( empty( $_GET['locale'] ) ) {
     97                        $locales = self::get_locales();
     98                        require( __DIR__ . '/views/all-locales.php' );
     99                } else {
     100                        require_once( WPORGPATH . 'translate/glotpress/locales/locales.php' );
     101                        $locale = GP_Locales::by_field( 'wp_locale', $_GET['locale'] );
     102                        require( __DIR__ . '/views/locale-details.php' );
     103                }
     104
     105                return ob_get_clean();
     106        }
     107
     108        /**
     109         * Get GlotPress locales that have a wp_locale, sorted alphabetically.
     110         *
     111         * @return array
     112         */
     113        protected static function get_locales() {
     114                require_once( WPORGPATH . 'translate/glotpress/locales/locales.php' );
     115
     116                $locales = GP_Locales::locales();
     117                $locales = array_filter( $locales, array( __CLASS__, 'filter_locale_for_wp' ) );
     118                usort( $locales, array( __CLASS__, 'sort_locales' ) );
     119
     120                return $locales;
     121        }
     122
     123        /**
     124         * Remove locales that are missing a wp_locale.
     125         *
     126         * This is a callback for array_filter().
     127         *
     128         * @param GP_Locale $element
     129         *
     130         * @return bool
     131         */
     132        protected static function filter_locale_for_wp( $element ) {
     133                if ( isset( $element->wp_locale ) ) {
     134                        return true;
     135                } else {
     136                        return false;
     137                }
     138        }
     139
     140        /**
     141         * Sort GlotPress locales alphabetically by the English name.
     142         *
     143         * @param GP_Locale $a
     144         * @param GP_Locale $b
     145         *
     146         * @return int
     147         */
     148        protected static function sort_locales( $a, $b ) {
     149                return strcmp( $a->english_name, $b->english_name );
     150        }
     151
     152        /**
     153         * Gather all the required data and cache it.
     154         */
     155        public function cache_locale_data() {
     156                error_log(__METHOD__);  // todo
     157
     158                global $wpdb;
     159                $locales = WP_I18n_Teams::get_locales();
     160
     161                $locale_wporg_info = $wpdb->get_results( "
     162                        SELECT locale, subdomain, latest_release
     163                        FROM locales
     164                        ORDER BY locale
     165                        LIMIT 400"
     166                );
     167
     168                // Reindex locale wporg info so that locales can be accessed directly
     169                foreach ( $locale_wporg_info as $index => $info ) {
     170                        unset( $locale_wporg_info[ $index ] );
     171                        $locale_wporg_info[ $info->locale ] = $info;
     172                }
     173
     174                foreach( $locales as $locale ) {
     175                        $contributors       = self::get_contributors( $locale );
     176                        $latest_release     = empty( $locale_wporg_info[ $locale->wp_locale ]->latest_release ) ? false : $locale_wporg_info[ $locale->wp_locale ]->latest_release;
     177                        $latest_branch      = explode( '.', $latest_release );
     178                        $latest_branch      = $latest_branch[0] .'.'. $latest_branch[1];
     179                        $rosetta_site_url   = empty( $locale_wporg_info[ $locale->wp_locale ]->subdomain ) ? '' : 'https://' . $locale_wporg_info[ $locale->wp_locale ]->subdomain . '.wordpress.org';
     180                        $localized_core_url = $rosetta_site_url && $latest_release ? sprintf( '%s/wordpress-%s-%s.zip', $rosetta_site_url, $latest_release, $locale->wp_locale ) : '';
     181                                // todo not sure localized url is always in this format? find where it's generated to verify. if have to derive it, try to get them all at once instead of 100+ calls
     182                        $language_pack_url  = $latest_release ? sprintf( 'https://downloads.wordpress.org/translation/core/%s/%s.zip', $latest_branch, $locale->wp_locale ) : '';
     183                           // todo verify that want to use $latest_branch here, vs $latest_release or CORE_LATEST_STABLE_BRANCH or CORE_LATEST_STABLE_RELEASE
     184                        $locale_status      = self::get_locale_status( $rosetta_site_url, $latest_release );
     185
     186                        $locale_data[ $locale->wp_locale ] = array(
     187                                'status'             => $locale_status,
     188                                'rosetta_site_url'   => $rosetta_site_url,
     189                                'localized_core_url' => $localized_core_url,
     190                                'language_pack_url'  => $language_pack_url,
     191                                'latest_release'     => $latest_release,
     192                                'validators'         => $contributors['validators'],
     193                                'translators'        => $contributors['translators'],
     194                        );
     195
     196                        $locale_data['status_counts'][ $locale_status ]++;
     197                }
     198
     199                error_log( count( $locale_data ) );    // todo
     200                set_transient( self::LOCALE_DATA_TRANSIENT_KEY, $locale_data );
     201        }
     202
     203        /**
     204         * Get the translators and validators for the given locale.
     205         *
     206         * @param GP_Locale $locale
     207         * @return array
     208         */
     209        public static function get_contributors( $locale ) {
     210                require_once( API_WPORG_PATH . 'core/credits/wp-credits.php' );
     211
     212                $credits = WP_Credits::factory( WP_CORE_LATEST_RELEASE, $locale );
     213                $results = $credits->get_results();
     214
     215                $contributors = array(
     216                        'validators'  => ! empty( $results['groups']['validators']['data'] )  ? $results['groups']['validators']['data']  : array(),
     217                        'translators' => ! empty( $results['groups']['translators']['data'] ) ? $results['groups']['translators']['data'] : array(),
     218                );
     219
     220                return $contributors;
     221        }
     222
     223        /**
     224         * Determine the status of the given locale
     225         *
     226         * @param string $rosetta_site_url
     227         * @param string $latest_release
     228         *
     229         * @return string
     230         */
     231        protected static function get_locale_status( $rosetta_site_url, $latest_release ) {
     232                if ( $rosetta_site_url ) {
     233                        if ( $latest_release ) {
     234                                $one_lower = WP_CORE_LATEST_RELEASE - 0.1;
     235
     236                                if ( $latest_release == WP_CORE_LATEST_RELEASE ) {
     237                                        $status = 'latest';
     238                                } else if ( substr( $latest_release, 0, 3 ) == substr( WP_CORE_LATEST_RELEASE, 0, 3 ) ) {
     239                                        $status = 'minor-behind';
     240                                } else if ( substr( $latest_release, 0, 3 ) == substr( $one_lower, 0, 3 ) ) {
     241                                        $status = 'major-behind-one';
     242                                } else {
     243                                        $status = 'major-behind-many';
     244                                }
     245                        } else {
     246                                $status = 'no-releases';
     247                        }
     248                } else {
     249                        $status = 'no-site';
     250                }
     251
     252                return $status;
     253        }
     254}
     255
     256$GLOBALS['wp_i18n_teams'] = new WP_I18n_Teams();
     257register_activation_hook(   __FILE__, array( $GLOBALS['wp_i18n_teams'], 'activate' ) );
     258register_deactivation_hook( __FILE__, array( $GLOBALS['wp_i18n_teams'], 'deactivate' ) );