| 1 | <?php |
| 2 | /* |
| 3 | Plugin Name: WP I18N Teams |
| 4 | Description: Generate list of locales statuses and contributors |
| 5 | Version: 0.9 |
| 6 | License: GPLv2 or later |
| 7 | Author: Marko Heijnen |
| 8 | Author URI: http://www.markoheijnen.com |
| 9 | Text Domain: wporg |
| 10 | */ |
| 11 | |
| 12 | require_once( WPORGPATH . 'translate/glotpress/locales/locales.php' ); |
| 13 | include 'inc/crawler.php'; |
| 14 | |
| 15 | // todo deploy new constants before deploying this -- API_CREDITS_DIR, GLOBAL_RELEASES_DIR |
| 16 | |
| 17 | class WP_I18n_Teams { |
| 18 | static $version = '0.9'; |
| 19 | |
| 20 | /** |
| 21 | * Constructor |
| 22 | */ |
| 23 | public function __construct() { |
| 24 | add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ) ); |
| 25 | |
| 26 | add_shortcode( 'wp-locales', array( $this, 'all_locales' ) ); |
| 27 | add_shortcode( 'wp-locale-contributors', array( $this, 'locale_contributors' ) ); |
| 28 | } |
| 29 | |
| 30 | /** |
| 31 | * Enqueue JavaScript and CSS |
| 32 | */ |
| 33 | public function enqueue_assets() { |
| 34 | wp_enqueue_style( 'wp-i18n-team', plugins_url( 'css/front.css', __FILE__ ), array(), self::$version ); |
| 35 | } |
| 36 | |
| 37 | /** |
| 38 | * Render the [wp-locales] shortcode. |
| 39 | * |
| 40 | * @param array $args |
| 41 | * @return string |
| 42 | */ |
| 43 | public function all_locales( $args ) { |
| 44 | $no_sites = $no_downloads = $latest = $minor_behind = $major_behind_one = $major_behind_many = 0; |
| 45 | $locales = self::get_locales(); |
| 46 | |
| 47 | $table = '<table>'; |
| 48 | $table .= '<thead>'; |
| 49 | $table .= '<tr>'; |
| 50 | $table .= '<th>' . __( 'Locale Name', 'wporg' ) . '</th>'; |
| 51 | $table .= '<th>' . __( 'Native Name', 'wporg' ) . '</th>'; |
| 52 | $table .= '<th>' . __( 'Locale Code', 'wporg' ) . '</th>'; |
| 53 | $table .= '<th>' . __( 'WordPress Locale', 'wporg' ) . '</th>'; |
| 54 | $table .= '<th>' . __( 'Version', 'wporg' ) . '</th>'; |
| 55 | $table .= '</tr>'; |
| 56 | $table .= '</thead>'; |
| 57 | $table .= '<tbody>'; |
| 58 | |
| 59 | foreach ( $locales as $locale ) { |
| 60 | $locale_data = WP_I18n_Team_Crawler::get_locale_data( $locale ); |
| 61 | $class = ''; |
| 62 | |
| 63 | if ( $locale_data['version'] ) { |
| 64 | $class = 'version'; |
| 65 | |
| 66 | $one_lower = WP_CORE_LATEST_RELEASE - 0.1; |
| 67 | |
| 68 | if ( $locale_data['version'] == WP_CORE_LATEST_RELEASE ) { |
| 69 | $class .= ' latest'; |
| 70 | |
| 71 | $latest++; |
| 72 | } |
| 73 | else if ( substr( $locale_data['version'], 0, 3 ) == substr( WP_CORE_LATEST_RELEASE, 0, 3 ) ) { |
| 74 | $class .= ' minor-behind'; |
| 75 | |
| 76 | $minor_behind++; |
| 77 | } |
| 78 | else if ( substr( $locale_data['version'], 0, 3 ) == substr( $one_lower, 0, 3 ) ) { |
| 79 | $class .= ' major-behind-one'; |
| 80 | |
| 81 | $major_behind_one++; |
| 82 | } |
| 83 | else { |
| 84 | $class .= ' major-behind-many'; |
| 85 | |
| 86 | $major_behind_many++; |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | if ( $locale_data['url'] ) { |
| 91 | $locale_code = '<a href="' . $locale_data['url'] . '">' . $locale->slug . '</a>'; |
| 92 | |
| 93 | if ( $locale_data['version'] ) { |
| 94 | $version = $locale_data['version']; |
| 95 | } |
| 96 | else { |
| 97 | $version = __( 'None', 'wporg' ); |
| 98 | |
| 99 | $no_downloads++; |
| 100 | } |
| 101 | } |
| 102 | else { |
| 103 | $locale_code = $locale->slug; |
| 104 | $version = __( 'No site', 'wporg' ); |
| 105 | |
| 106 | $no_sites++; |
| 107 | } |
| 108 | |
| 109 | $table .= '<tr class="' . $class . '">'; |
| 110 | $table .= '<td>' . $locale->english_name . '</td>'; |
| 111 | $table .= '<td>' . $locale->native_name . '</td>'; |
| 112 | $table .= '<td>' . $locale_code . '</td>'; |
| 113 | $table .= '<td>' . $locale->wp_locale . '</td>'; |
| 114 | $table .= '<td>' . $version . '</td>'; |
| 115 | $table .= '</tr>'; |
| 116 | } |
| 117 | |
| 118 | $table .= '</tbody>'; |
| 119 | $table .= '</table>'; |
| 120 | |
| 121 | $html = '<p>'; |
| 122 | $html .= sprintf( |
| 123 | __( '%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' ), |
| 124 | '<strong class="i18n-label latest">' . $latest . '</strong>', |
| 125 | '<strong class="i18n-label minor-behind">' . $minor_behind . '</strong>', |
| 126 | '<strong class="i18n-label major-behind-one">' . $major_behind_one . '</strong>', |
| 127 | '<strong class="i18n-label major-behind-many">' . $major_behind_many . '</strong>', |
| 128 | '<strong class="i18n-label">' . ( $no_sites + $no_downloads ) . '</strong>' |
| 129 | ); |
| 130 | $html .= '</p>'; |
| 131 | |
| 132 | $html = '<div class="translators-info">' . $html . $table . '</div>'; |
| 133 | |
| 134 | return $html; |
| 135 | } |
| 136 | |
| 137 | /** |
| 138 | * Get GlotPress locales that have a wp_locale, sorted alphabetically. |
| 139 | * |
| 140 | * @return array |
| 141 | */ |
| 142 | protected static function get_locales() { |
| 143 | $locales = GP_Locales::locales(); |
| 144 | $locales = array_filter( $locales, array( __CLASS__, 'filter_locale_for_wp' ) ); |
| 145 | usort( $locales, array( __CLASS__, 'sort_locales' ) ); |
| 146 | |
| 147 | return $locales; |
| 148 | } |
| 149 | |
| 150 | /** |
| 151 | * Remove locales that are missing a wp_locale. |
| 152 | * |
| 153 | * This is a callback for array_filter(). |
| 154 | * |
| 155 | * @param GP_Locale $element |
| 156 | * @return bool |
| 157 | */ |
| 158 | protected static function filter_locale_for_wp( $element ) { |
| 159 | if ( ! isset( $element->wp_locale ) ) { |
| 160 | return false; |
| 161 | } |
| 162 | |
| 163 | return true; |
| 164 | } |
| 165 | |
| 166 | /** |
| 167 | * Sort GlotPress locales alphabetically by the English name. |
| 168 | * |
| 169 | * @param GP_Locale $a |
| 170 | * @param GP_Locale $b |
| 171 | * |
| 172 | * @return int |
| 173 | */ |
| 174 | protected static function sort_locales( $a, $b ) { |
| 175 | return strcmp( $a->english_name, $b->english_name ); |
| 176 | } |
| 177 | |
| 178 | /** |
| 179 | * Render the [wp-locale-contributors] shortcode |
| 180 | * |
| 181 | * @param array $args |
| 182 | * @return string |
| 183 | */ |
| 184 | public function locale_contributors( $args ) { |
| 185 | $locale = GP_Locales::by_field( 'wp_locale', $_GET['locale'] ); |
| 186 | |
| 187 | if ( $locale ) { |
| 188 | $locale_data = WP_I18n_Team_Crawler::get_locale_data( $locale ); |
| 189 | |
| 190 | $content = "<h2>Validators</h2>"; |
| 191 | if ( ! empty( $locale_data['validators'] ) ) { |
| 192 | $content .= '<ul>'; |
| 193 | foreach ( $locale_data['validators'] as $validator ) { |
| 194 | $content .= '<li>'; |
| 195 | $content .= $validator[0]; |
| 196 | $content .= '</li>'; |
| 197 | } |
| 198 | $content .= '</ul>'; |
| 199 | } else { |
| 200 | $content .= '<p>' . __( 'No validators for the language.', 'wporg' ) . '</p>'; |
| 201 | } |
| 202 | |
| 203 | if ( ! empty( $locale_data['translators'] ) ) { |
| 204 | $content .= "<h2>Translators</h2>"; |
| 205 | $content .= '<ul>'; |
| 206 | foreach ( $locale_data['translators'] as $translator ) { |
| 207 | $content .= '<li>'; |
| 208 | $content .= $translator; |
| 209 | $content .= '</li>'; |
| 210 | } |
| 211 | $content .= '</ul>'; |
| 212 | } |
| 213 | } else { |
| 214 | $content = __( 'Invalid locale.', 'wporg' ); |
| 215 | } |
| 216 | |
| 217 | return $content; |
| 218 | } |
| 219 | |
| 220 | } |
| 221 | |
| 222 | $GLOBALS['wp_i18n_teams'] = new WP_I18n_Teams(); |