Index: translate/gp-plugins/wporg-projects-wp-plugins-overview.php
===================================================================
--- translate/gp-plugins/wporg-projects-wp-plugins-overview.php	(revision 0)
+++ translate/gp-plugins/wporg-projects-wp-plugins-overview.php	(working copy)
@@ -0,0 +1,129 @@
+<?php
+
+class GP_WPorg_Route_WP_Plugins extends GP_Route {
+
+	public function get_plugin_projects( $project_slug ) {
+		global $gpdb;
+
+		$project_path = 'wp-plugins/' . $project_slug;
+		$project = GP::$project->by_path( $project_path );
+		if ( ! $project ) {
+			return $this->die_with_404();
+		}
+
+		$rows = $gpdb->get_results( "
+			SELECT
+				path, locale, locale_slug,
+				(100 * stats.current/stats.all) as percent_complete,
+				stats.waiting+stats.fuzzy as waiting_strings
+			FROM {$gpdb->prefix}project_translation_status stats
+				LEFT JOIN {$gpdb->prefix}projects p ON stats.project_id = p.id
+			WHERE
+				p.path = '$project_path'
+		" );
+
+		// Split out into $[Locale][Project] = %
+		$translation_locale_statuses = array();
+		foreach ( $rows as $set ) {
+
+			// Find unique locale key.
+			$locale_key = $set->locale;
+			if ( 'default' != $set->locale_slug ) {
+				$locale_key = $set->locale . '/' . $set->locale_slug;
+			}
+
+			foreach ( $this->get_active_sub_projects( $project ) as $sub_project_id => $sub_project ) {
+				$translation_set = GP::$translation_set->by_project_id_slug_and_locale(
+					$sub_project_id,
+					$set->locale_slug,
+					$locale_key
+				);
+
+				if ( $translation_set ) {
+					/*
+					 * > 50% round down, so that a project with all strings except 1 translated shows 99%, instead of 100%.
+					 * < 50% round up, so that a project with just a few strings shows 1%, instead of 0%.
+					 */
+					$percent_complete = (int) $translation_set->current_count() / (int) $translation_set->all_count() * 100;
+					$translation_locale_statuses[ $locale_key ][ $sub_project->slug ] = ( $percent_complete > 50 ) ? floor( $percent_complete ) : ceil( $percent_complete );
+
+					// Increment the amount of waiting strings.
+					if ( ! isset( $translation_locale_statuses[ $locale_key ]['waiting'] ) ) {
+						$translation_locale_statuses[ $locale_key ]['waiting'] = 0;
+					}
+					$translation_locale_statuses[ $locale_key ]['waiting'] += (int) $translation_set->all_count() - (int) $translation_set->current_count();
+				}
+			}
+			ksort( $translation_locale_statuses[ $locale_key ], SORT_NATURAL );
+		}
+		unset( $project_path, $locale_key, $set, $sub_project_id, $sub_project, $translation_set );
+
+		// Calculate a list of [Locale] = % subtotals
+		$translation_locale_complete = array();
+		foreach ( $rows as $set ) {
+			$translation_locale_complete[ $set->locale ] = (float) $set->percent_complete;
+		}
+		unset( $rows, $set );
+
+		// Sort by Percent Complete, secondly by Slug
+		uksort( $translation_locale_complete, function ( $a, $b ) use ( $translation_locale_complete ) {
+			if ( $translation_locale_complete[ $a ] < $translation_locale_complete[ $b ] ) {
+				return 1;
+			} elseif ( $translation_locale_complete[ $a ] == $translation_locale_complete[ $b ] ) {
+				return strnatcmp( $a, $b );
+			} else {
+				return -1;
+			}
+		} );
+
+		$project->icon = wporg_get_plugin_icon( $project->slug, 64 );
+
+		$this->tmpl( 'project-wp-plugin', get_defined_vars() );
+	}
+
+	/**
+	 * Retrieves active sub projects.
+	 *
+	 * @param  GP_Project $project           The parent project
+	 * @param  bool       $with_sub_projects Whether sub projects should be fetched too.
+	 *                                       Default false.
+	 * @return array List of sub projects.
+	 */
+	private function get_active_sub_projects( $project, $with_sub_projects = false ) {
+		global $gpdb;
+
+		$_projects = $project->many( "
+			SELECT *
+			FROM {$gpdb->projects}
+			WHERE
+				parent_project_id = %d AND
+				active = 1
+			ORDER BY id ASC
+		", $project->id );
+
+		$projects = array();
+		foreach ( $_projects as $project ) {
+			$projects[ $project->id ] = $project;
+
+			if ( $with_sub_projects ) {
+				// e.g. wp/dev/admin/network
+				$sub_projects = $project->many( "
+					SELECT *
+					FROM {$gpdb->projects}
+					WHERE
+						parent_project_id = %d AND
+						active = 1
+					ORDER BY id ASC
+				", $project->id );
+
+				foreach ( $sub_projects as $sub_project ) {
+					$projects[ $sub_project->id ] = $sub_project;
+				}
+				unset( $sub_projects);
+			}
+		}
+		unset( $_projects );
+
+		return $projects;
+	}
+}

Property changes on: translate/gp-plugins/wporg-projects-wp-plugins-overview.php
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: translate/gp-plugins/wporg-routes/wporg-routes.php
===================================================================
--- translate/gp-plugins/wporg-routes/wporg-routes.php	(revision 2013)
+++ translate/gp-plugins/wporg-routes/wporg-routes.php	(working copy)
@@ -41,6 +41,9 @@
 		GP::$router->prepend( "/locale/$locale/$path", array( 'GP_WPorg_Route_Locale', 'get_locale_projects' ) );
 		GP::$router->prepend( "/locale/$locale/$path/$path", array( 'GP_WPorg_Route_Locale', 'get_locale_projects' ) );
 		GP::$router->prepend( "/locale/$locale/$path/$path/$path", array( 'GP_WPorg_Route_Locale', 'get_locale_project' ) );
+
+		$project = '(.+?)';
+		GP::$router->prepend( "/projects/wp-plugins/$project", array( 'GP_WPorg_Route_WP_Plugins', 'get_plugin_projects' ) );
 	}
 }
 
Index: translate/gp-templates/projects-wp-plugins.php
===================================================================
--- translate/gp-templates/projects-wp-plugins.php	(revision 0)
+++ translate/gp-templates/projects-wp-plugins.php	(working copy)
@@ -0,0 +1,112 @@
+<?php
+
+$edit_link = gp_link_project_edit_get( $project, __('(edit)') );
+
+gp_title( sprintf( __( '%s &lt; GlotPress' ), esc_html( $project->name ) ) );
+gp_breadcrumb_project( $project );
+
+wp_enqueue_script( 'common' );
+wp_enqueue_script( 'tablesorter' );
+
+gp_tmpl_header();
+?>
+
+<div class="project-header">
+	<p class="project-description"><?php echo apply_filters( 'project_description', $project->description, $project ); ?></p>
+
+	<div class="project-box">
+		<div class="project-box-header">
+			<div class="project-icon">
+				<?php echo $project->icon; ?>
+			</div>
+
+			<ul class="project-meta">
+				<li class="project-name"><?php echo $project->name; ?> <?php echo $edit_link; ?></li>
+			</ul>
+		</div>
+	</div>
+</div>
+
+<div class="stats-table">
+	<table id="stats-table" class="table">
+		<thead>
+			<tr>
+				<th class="title"><?php _e( 'Locale' ); ?></th>
+				<th class="title"><?php _e( 'Development' ); ?></th>
+				<th class="title"><?php _e( 'Development Readme' ); ?></th>
+				<th class="title"><?php _e( 'Stable' ); ?></th>
+				<th class="title"><?php _e( 'Stable Readme' ); ?></th>
+				<th class="title"><?php _e( 'Waiting' ); ?></th>
+			</tr>
+		</thead>
+		<tbody>
+			<?php
+			foreach ( $translation_locale_complete as $locale_slug => $completeness ) :
+				$gp_locale = GP_Locales::by_slug( $locale_slug );
+				$set_slug = 'default';
+				// Variants (de/formal for example) don't have GP_Locales in this context
+				if ( ! $gp_locale && ( list( $base_locale_slug, $set_slug ) = explode( '/', $locale_slug ) ) ) {
+					$gp_locale = clone GP_Locales::by_slug( $base_locale_slug );
+					// Just append it for now..
+					$gp_locale->wp_locale .= '/' . $set_slug;
+				}
+				if ( ! $gp_locale || ! $gp_locale->wp_locale ) {
+					continue;
+				}
+			?>
+				<tr>
+					<th title="<?php echo esc_attr( $gp_locale->english_name ); ?>">
+						<a href="<?php echo gp_url_join( 'locale', $gp_locale->slug, $set_slug ); ?>">
+							<?php echo esc_html( $gp_locale->english_name ); ?>
+						</a>
+					</th>
+					<?php
+
+					if ( $translation_locale_statuses[ $locale_slug ] ) {
+						foreach ( $translation_locale_statuses[ $locale_slug ] as $slug => $percent ) {
+							$projecturl = gp_url_join( 'locale', $gp_locale->slug, $set_slug, $project->path );
+
+							if ( 'waiting' === $slug ) {
+								// Color code it on -0~500 waiting strings
+								$percent_class = 100-min( (int) ( $percent / 50 ) * 10, 100 );
+								// It's only 100 if it has 0 strings.
+								if ( 100 == $percent_class && $percent ) {
+									$percent_class = 90;
+								}
+								$percent_class = 'percent' . $percent_class;
+								echo '<td data-sort-value="'. esc_attr( $percent ) . '" class="' . $percent_class .'"><a href="' . $projecturl . '">' . number_format( $percent ) . '</a></td>';
+							} else {
+								$percent_class = 'percent' . (int) ( $percent / 10 ) * 10;
+								echo '<td data-sort-value="' . esc_attr( $percent ) . '" class="' . $percent_class .'">';
+								gp_link( gp_url_project( $project->path, gp_url_join( $locale_slug, $set_slug ), array( 'filters[translated]' => 'yes', 'filters[status]' => 'current') ), "$percent%" );
+								echo '</td>';
+							}
+						}
+					} else {
+						echo '<td class="none" data-sort-value="-1">&mdash;</td>';
+						echo '<td class="none" data-sort-value="-1">&mdash;</td>';
+						echo '<td class="none" data-sort-value="-1">&mdash;</td>';
+						echo '<td class="none" data-sort-value="-1">&mdash;</td>';
+						echo '<td class="none" data-sort-value="-1">&mdash;</td>';
+					}
+					?>
+				</tr>
+			<?php endforeach; ?>
+		</tbody>
+	</table>
+</div>
+
+<script type="text/javascript">
+jQuery( function( $ ) {
+	$( '#stats-table' ).tablesorter( {
+		textExtraction: function( node ) {
+			var cellValue = $( node ).text(),
+				sortValue = $( node ).data( 'sortValue' );
+
+			return ( undefined !== sortValue ) ? sortValue : cellValue;
+		}
+	});
+});
+</script>
+
+<?php gp_tmpl_footer();

Property changes on: translate/gp-templates/projects-wp-plugins.php
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
