<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[12063] sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers: Translate. Add new status in the gp-translation-helpers plugin</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="http://meta.trac.wordpress.org/changeset/12063">12063</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"http://meta.trac.wordpress.org/changeset/12063","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>amieiro</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2022-09-15 15:13:17 +0000 (Thu, 15 Sep 2022)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Translate. Add new status in the gp-translation-helpers plugin</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsgptranslationhelperscssdiscussioncss">sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/css/discussion.css</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsgptranslationhelpersgptranslationhelpersphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/gp-translation-helpers.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsgptranslationhelpershelpershelpertranslationdiscussionphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/helpers/helper-translation-discussion.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsgptranslationhelpersincludesclassgpnotificationsphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/includes/class-gp-notifications.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsgptranslationhelpersincludesclassgproutetranslationhelpersphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/includes/class-gp-route-translation-helpers.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsgptranslationhelpersincludesclassgptranslationhelpersphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/includes/class-gp-translation-helpers.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsgptranslationhelpersincludesclasswporgnotificationsphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/includes/class-wporg-notifications.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsgptranslationhelpersjsrejectfeedbackjs">sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/js/reject-feedback.js</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsgptranslationhelperstemplatesgptemplatesoverridestranslationroweditormetastatusphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/templates/gp-templates-overrides/translation-row-editor-meta-status.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsgptranslationhelperstemplatesoriginalpermalinkphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/templates/original-permalink.php</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsgptranslationhelperstemplatesdiscussionsdashboardphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/templates/discussions-dashboard.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsgptranslationhelperstemplatesgptemplatesoverrideslocaleprojectsphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/templates/gp-templates-overrides/locale-projects.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsgptranslationhelperscssdiscussioncss"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/css/discussion.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/css/discussion.css        2022-09-14 16:56:00 UTC (rev 12062)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/css/discussion.css  2022-09-15 15:13:17 UTC (rev 12063)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -147,7 +147,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> .modal-btn {
</span><span class="cx" style="display: block; padding: 0 10px">        float: right;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-.gp-btn-style:hover, #respond form .form-submit .submit:hover {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.gp-btn-style:hover, #respond form .form-submit .submit:hover, .other-comments:hover{
</ins><span class="cx" style="display: block; padding: 0 10px">         background-color: var(--gp-color-btn-primary-hover-bg);
</span><span class="cx" style="display: block; padding: 0 10px">        border-color: var(--gp-color-btn-primary-hover-border);
</span><span class="cx" style="display: block; padding: 0 10px">        color: var(--gp-color-btn-primary-hover-text);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -248,3 +248,19 @@
</span><span class="cx" style="display: block; padding: 0 10px"> a.comment-reply-link {
</span><span class="cx" style="display: block; padding: 0 10px">        margin: 2px !important;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.other-comments{
+       font-size: .7em;
+       background: #0285ba;
+       color: #fff !important;
+       padding: 3px;
+       text-decoration: none;
+       display: inline-block;
+       text-decoration: none !important;
+       margin-top: 8px;
+}
+.discussions-table-head{
+       background-color: var(--gp-color-canvas-subtle) !important;
+}
+.bulk-comment-item{
+       font-size: .8em;
+}
</ins></span></pre></div>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsgptranslationhelpersgptranslationhelpersphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/gp-translation-helpers.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/gp-translation-helpers.php        2022-09-14 16:56:00 UTC (rev 12062)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/gp-translation-helpers.php  2022-09-15 15:13:17 UTC (rev 12063)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -7,7 +7,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">  * Plugin name:     GP Translation Helpers
</span><span class="cx" style="display: block; padding: 0 10px">  * Plugin URI:      https://github.com/GlotPress/gp-translation-helpers
</span><span class="cx" style="display: block; padding: 0 10px">  * Description:     GlotPress plugin to discuss the strings that are being translated in GlotPress.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Version:         0.0.2
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Version:         0.0.3
</ins><span class="cx" style="display: block; padding: 0 10px">  * Requires PHP:    7.4
</span><span class="cx" style="display: block; padding: 0 10px">  * Author:          the GlotPress team
</span><span class="cx" style="display: block; padding: 0 10px">  * Author URI:      https://glotpress.blog
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -39,3 +39,4 @@
</span><span class="cx" style="display: block; padding: 0 10px"> add_action( 'gp_init', array( 'GP_Translation_Helpers', 'init' ) );
</span><span class="cx" style="display: block; padding: 0 10px"> add_action( 'gp_init', array( 'WPorg_GlotPress_Notifications', 'init' ) );    // todo: include this class in a different plugin.
</span><span class="cx" style="display: block; padding: 0 10px"> add_action( 'gp_init', array( 'WPorg_GlotPress_Customizations', 'init' ) );    // todo: include this class in a different plugin.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+add_filter( 'gp_enable_changesrequested_status', '__return_true' ); // todo: remove this filter when this plugin will be merged in the GlotPress core.
</ins></span></pre></div>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsgptranslationhelpershelpershelpertranslationdiscussionphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/helpers/helper-translation-discussion.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/helpers/helper-translation-discussion.php 2022-09-14 16:56:00 UTC (rev 12062)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/helpers/helper-translation-discussion.php   2022-09-15 15:13:17 UTC (rev 12063)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -40,6 +40,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">        public $load_inline = true;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * Indicates whether we're currently using a temporary post.
+        *
+        * @since 0.0.2
+        * @var object|null
+        */
+       public static $temporary_post = null;
+
+       /**
</ins><span class="cx" style="display: block; padding: 0 10px">          * The post type used to store the comments.
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 0.0.1
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -89,6 +97,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">        public function after_constructor() {
</span><span class="cx" style="display: block; padding: 0 10px">                $this->register_post_type_and_taxonomy();
</span><span class="cx" style="display: block; padding: 0 10px">                add_filter( 'pre_comment_approved', array( $this, 'comment_moderation' ), 10, 2 );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                add_filter( 'comments_open', array( $this, 'comments_open_override' ), 10, 2 );
</ins><span class="cx" style="display: block; padding: 0 10px">                 add_filter( 'map_meta_cap', array( $this, 'map_comment_meta_caps' ), 10, 4 );
</span><span class="cx" style="display: block; padding: 0 10px">                add_filter( 'user_has_cap', array( $this, 'give_user_read_cap' ), 10, 3 );
</span><span class="cx" style="display: block; padding: 0 10px">                add_filter( 'post_type_link', array( $this, 'rewrite_original_post_type_permalink' ), 10, 2 );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -252,6 +261,28 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * Enable showing the comment form on non-existing posts.
+        *
+        * @param      boolean $open     Whether the comments are open or not.
+        * @param      int     $post_id  The post id.
+        *
+        * @return     bool    Whether the comments are open or not.
+        */
+       public function comments_open_override( $open, $post_id ) {
+               if ( self::is_temporary_post_id( $post_id ) ) {
+                       return true;
+               }
+
+               // If we just had to define a temporary post, the post id can also be 0.
+               // This is due to a code change in core in this commit:
+               // https://github.com/WordPress/WordPress/commit/1069ac4afda821742cf7f600412aacc139013a55
+               if ( self::$temporary_post && 0 === $post_id ) {
+                       return true;
+               }
+               return $open;
+       }
+
+       /**
</ins><span class="cx" style="display: block; padding: 0 10px">          * Updates the comment's approval status before it is set.
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * It only updates the approved status if the user has previous translations.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -365,7 +396,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        public static function maybe_get_temporary_post( $post_id ) {
</span><span class="cx" style="display: block; padding: 0 10px">                if ( self::is_temporary_post_id( $post_id ) ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        return new Gth_Temporary_Post( $post_id );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 self::$temporary_post = new Gth_Temporary_Post( $post_id );
+                       return self::$temporary_post;
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                return get_post( $post_id );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -526,7 +558,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                'post'                 => $post,
</span><span class="cx" style="display: block; padding: 0 10px">                                'translation_id'       => isset( $this->data['translation_id'] ) ? $this->data['translation_id'] : null,
</span><span class="cx" style="display: block; padding: 0 10px">                                'locale_slug'          => $this->data['locale_slug'],
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                'original_permalink'   => $this->data['original_permalink'],
</del><span class="cx" style="display: block; padding: 0 10px">                                 'original_id'          => $this->data['original_id'],
</span><span class="cx" style="display: block; padding: 0 10px">                                'project'              => $this->data['project'],
</span><span class="cx" style="display: block; padding: 0 10px">                                'translation_set_slug' => $this->data['translation_set_slug'],
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -654,6 +685,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        'replyto'        => sprintf( $args['reply_to_text'], $comment->comment_author ),
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                if ( get_option( 'page_comments' ) ) {
+                       $permalink = str_replace( '#comment-' . $comment->comment_ID, '', get_comment_link( $comment ) );
+               } else {
+                       $permalink = get_permalink( $post->ID );
+               }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 $data_attribute_string = '';
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                foreach ( $data_attributes as $name => $value ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -671,7 +708,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                'unapproved'      => false,
</span><span class="cx" style="display: block; padding: 0 10px">                                                'moderation-hash' => false,
</span><span class="cx" style="display: block; padding: 0 10px">                                        ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $args['original_permalink']
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $permalink
</ins><span class="cx" style="display: block; padding: 0 10px">                                 )
</span><span class="cx" style="display: block; padding: 0 10px">                        ) . '#' . $args['respond_id'],
</span><span class="cx" style="display: block; padding: 0 10px">                        $data_attribute_string,
</span></span></pre></div>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsgptranslationhelpersincludesclassgpnotificationsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/includes/class-gp-notifications.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/includes/class-gp-notifications.php       2022-09-14 16:56:00 UTC (rev 12062)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/includes/class-gp-notifications.php 2022-09-15 15:13:17 UTC (rev 12063)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -34,9 +34,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                if ( ( '0' !== $comment->comment_parent ) ) { // Notify to the thread only if the comment is in a thread.
</span><span class="cx" style="display: block; padding: 0 10px">                                        self::send_emails_to_thread_commenters( $comment, $comment_meta );
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                if ( ( '0' === $comment->comment_parent ) && array_key_exists( 'reject_reason', $comment_meta ) && ( ! empty( $comment_meta['reject_reason'] ) ) ) {  // Notify a rejection without parent comments.
-                                       self::send_rejection_email_to_translator( $comment, $comment_meta );
-                               }
</del><span class="cx" style="display: block; padding: 0 10px">                                 $root_comment      = self::get_root_comment_in_a_thread( $comment );
</span><span class="cx" style="display: block; padding: 0 10px">                                $root_comment_meta = get_comment_meta( $root_comment->comment_ID );
</span><span class="cx" style="display: block; padding: 0 10px">                                if ( array_key_exists( 'comment_topic', $root_comment_meta ) ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -49,6 +46,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        self::send_emails_to_validators( $comment, $comment_meta );
</span><span class="cx" style="display: block; padding: 0 10px">                                                        break;
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                } elseif ( ( '0' === $comment->comment_parent ) ) {  // Notify an approval, rejection or fuzzy without parent comments.
+                                       self::send_action_email_to_translator( $comment, $comment_meta );
</ins><span class="cx" style="display: block; padding: 0 10px">                                 }
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -103,7 +102,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-         * Sends the reject notification to the translator.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  * Sends the action notification (approval, rejection, fuzzy) to the translator.
</ins><span class="cx" style="display: block; padding: 0 10px">          *
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 0.0.2
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -112,14 +111,16 @@
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @return void
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        public static function send_rejection_email_to_translator( WP_Comment $comment, array $comment_meta ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public static function send_action_email_to_translator( WP_Comment $comment, array $comment_meta ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                 $translation_id = $comment_meta['translation_id'];
</span><span class="cx" style="display: block; padding: 0 10px">                $translation    = GP::$translation->get( $translation_id );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $translator     = get_user_by( 'id', $translation->user_id_last_modified );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $translator     = get_user_by( 'id', $translation->user_id );
</ins><span class="cx" style="display: block; padding: 0 10px">                 if ( false === $translator ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $translator = get_user_by( 'id', $translation->user_id );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $translator = get_user_by( 'id', $translation->user_id_last_modified );
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                self::send_emails( $comment, $comment_meta, array( $translator->user_email ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if ( false === $translator ) {
+                       self::send_emails( $comment, $comment_meta, array( $translator->user_email ) );
+               }
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -421,6 +422,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                if ( isset( $comment_meta['reject_reason'][0] ) && ! empty( maybe_unserialize( $comment_meta['reject_reason'][0] ) ) ) {
+                       $reasons         = array();
+                       $comment_reasons = Helper_Translation_Discussion::get_comment_reasons();
+                       $reasons         = array_map(
+                               function( $reason ) use ( $comment_reasons ) {
+                                       if ( array_key_exists( $reason, $comment_reasons ) ) {
+                                               return $comment_reasons[ $reason ]['name'];
+                                       }
+                               },
+                               maybe_unserialize( $comment_meta['reject_reason'][0] )
+                       );
+                       /* translators: The reason(s) for rejection. */
+                       $output .= '- ' . wp_kses( sprintf( __( '<strong>Reason(s):</strong> %s', 'glotpress' ), implode( ', ', $reasons ) ), array( 'strong' => array() ) ) . '<br/>';
+               }
</ins><span class="cx" style="display: block; padding: 0 10px">                 /* translators: The comment made. */
</span><span class="cx" style="display: block; padding: 0 10px">                $output .= '- ' . wp_kses( sprintf( __( '<strong>Comment:</strong> %s', 'glotpress' ), $comment->comment_content ), array( 'strong' => array() ) ) . '<br/>';
</span><span class="cx" style="display: block; padding: 0 10px">                if ( empty( self::$related_comments ) ) {
</span></span></pre></div>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsgptranslationhelpersincludesclassgproutetranslationhelpersphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/includes/class-gp-route-translation-helpers.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/includes/class-gp-route-translation-helpers.php   2022-09-14 16:56:00 UTC (rev 12062)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/includes/class-gp-route-translation-helpers.php     2022-09-15 15:13:17 UTC (rev 12063)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -26,6 +26,45 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * Loads the 'discussions-dashboard' template.
+        *
+        * @since 0.0.2
+        *
+        * @param string|null $locale_slug          Optional. The locale slug. E.g. "es".
+        *
+        * @return void
+        */
+       public function discussions_dashboard( $locale_slug ) {
+               if ( ! is_user_logged_in() ) {
+                       $this->die_with_404();
+               }
+               $all_comments_count  = count(
+                       get_comments(
+                               array(
+                                       'meta_key'   => 'locale',
+                                       'meta_value' => $locale_slug,
+                               )
+                       )
+               );
+               $comments_per_page   = 12;
+               $total_pages         = (int) ceil( $all_comments_count / $comments_per_page );
+               $page_num_from_query = get_query_var( 'page' );
+               $page_number         = ( ! empty( $page_num_from_query ) && is_int( $page_num_from_query ) ) ? $page_num_from_query : 1;
+               $gp_locale           = GP_Locales::by_slug( $locale_slug );
+               $args                = array(
+                       'number'     => $comments_per_page,
+                       'meta_key'   => 'locale',
+                       'meta_value' => $locale_slug,
+                       'paged'      => $page_number,
+               );
+
+               $comments_query = new WP_Comment_Query( $args );
+               $comments       = $comments_query->comments;
+
+               $this->tmpl( 'discussions-dashboard', get_defined_vars() );
+       }
+
+       /**
</ins><span class="cx" style="display: block; padding: 0 10px">          * Loads the 'original-permalink' template.
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 0.0.2
</span></span></pre></div>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsgptranslationhelpersincludesclassgptranslationhelpersphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/includes/class-gp-translation-helpers.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/includes/class-gp-translation-helpers.php 2022-09-14 16:56:00 UTC (rev 12062)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/includes/class-gp-translation-helpers.php   2022-09-15 15:13:17 UTC (rev 12063)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -67,7 +67,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                add_thickbox();
</span><span class="cx" style="display: block; padding: 0 10px">                gp_enqueue_style( 'thickbox' );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                wp_register_style( 'gp-discussion-css', plugins_url( '/../css/discussion.css', __FILE__ ), array(), '20220801' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         wp_register_style(
+                       'gp-discussion-css',
+                       plugins_url( 'css/discussion.css', __DIR__ ),
+                       array(),
+                       filemtime( plugin_dir_path( __DIR__ ) . 'css/discussion.css' )
+               );
</ins><span class="cx" style="display: block; padding: 0 10px">                 gp_enqueue_style( 'gp-discussion-css' );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                add_filter( 'gp_translation_row_template_more_links', array( $this, 'translation_row_template_more_links' ), 10, 5 );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -75,7 +80,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                add_filter(
</span><span class="cx" style="display: block; padding: 0 10px">                        'gp_tmpl_load_locations',
</span><span class="cx" style="display: block; padding: 0 10px">                        function( $locations, $template, $args, $template_path ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                if ( 'translation-row-editor-meta-status' === $template ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         if ( 'translation-row-editor-meta-status' === $template || 'locale-projects' === $template ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                         array_unshift( $locations, dirname( dirname( __FILE__ ) ) . '/templates/gp-templates-overrides/' );
</span><span class="cx" style="display: block; padding: 0 10px">                                } else {
</span><span class="cx" style="display: block; padding: 0 10px">                                        $locations[] = dirname( dirname( __FILE__ ) ) . '/templates/';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -189,10 +194,21 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                wp_register_style( 'gp-translation-helpers-css', plugins_url( 'css/translation-helpers.css', __DIR__ ), '', '20220801' ); // todo: add the version as global element.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         wp_register_style(
+                       'gp-translation-helpers-css',
+                       plugins_url( 'css/translation-helpers.css', __DIR__ ),
+                       array(),
+                       filemtime( plugin_dir_path( __DIR__ ) . 'css/translation-helpers.css' )
+               );
</ins><span class="cx" style="display: block; padding: 0 10px">                 gp_enqueue_style( 'gp-translation-helpers-css' );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                wp_register_script( 'gp-translation-helpers', plugins_url( '/js/translation-helpers.js', __DIR__ ), array( 'gp-editor' ), '20220801', true );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         wp_register_script(
+                       'gp-translation-helpers',
+                       plugins_url( 'js/translation-helpers.js', __DIR__ ),
+                       array( 'gp-editor' ),
+                       filemtime( plugin_dir_path( __DIR__ ) . 'js/translation-helpers.js' ),
+                       true
+               );
</ins><span class="cx" style="display: block; padding: 0 10px">                 gp_enqueue_scripts( array( 'gp-translation-helpers' ) );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                wp_localize_script( 'gp-translation-helpers', '$gp_translation_helpers_settings', $translation_helpers_settings );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -311,6 +327,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                GP::$router->prepend( "/$project/(\d+)(?:/$locale/$dir)?(/\d+)?", array( 'GP_Route_Translation_Helpers', 'original_permalink' ), 'get' );
</span><span class="cx" style="display: block; padding: 0 10px">                GP::$router->prepend( "/$project/-get-translation-helpers/$id", array( 'GP_Route_Translation_Helpers', 'ajax_translation_helpers' ), 'get' );
</span><span class="cx" style="display: block; padding: 0 10px">                GP::$router->prepend( "/$project/$locale/$dir/-get-translation-helpers/$id", array( 'GP_Route_Translation_Helpers', 'ajax_translation_helpers_locale' ), 'get' );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                GP::$router->prepend( "/locale/$locale/$dir/discussions/?", array( 'GP_Route_Translation_Helpers', 'discussions_dashboard' ), 'get' );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -363,7 +380,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        return;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                wp_register_script( 'gp-comment-feedback-js', plugins_url( '/../js/reject-feedback.js', __FILE__ ), array( 'jquery', 'gp-common', 'gp-editor', 'thickbox' ), '20220812' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         wp_register_script(
+                       'gp-comment-feedback-js',
+                       plugins_url( 'js/reject-feedback.js', __DIR__ ),
+                       array( 'jquery', 'gp-common', 'gp-editor', 'thickbox' ),
+                       filemtime( plugin_dir_path( __DIR__ ) . 'js/reject-feedback.js' )
+               );
</ins><span class="cx" style="display: block; padding: 0 10px">                 gp_enqueue_script( 'gp-comment-feedback-js' );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                wp_localize_script(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -402,9 +424,18 @@
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span><span class="cx" style="display: block; padding: 0 10px">                $comment              = sanitize_text_field( $_POST['data']['comment'] );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( ! $locale_slug || ! $translation_id_array || ! $original_id_array || ( ! $comment_reason && ! $comment ) ) {
-                       wp_send_json_error();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if ( ! $locale_slug ) {
+                       wp_send_json_error( 'Oops! Locale slug missing' );
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                if ( ! $translation_id_array ) {
+                       wp_send_json_error( 'Oops! Translation ID missing' );
+               }
+               if ( ! $original_id_array ) {
+                       wp_send_json_error( 'Oops! Original ID missing' );
+               }
+               if ( ! $comment_reason && ! $comment ) {
+                       wp_send_json_error( 'Oops! No comment and reason found' );
+               }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // Get original_id and translation_id of first string in the array
</span><span class="cx" style="display: block; padding: 0 10px">                $first_original_id    = array_shift( $original_id_array );
</span></span></pre></div>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsgptranslationhelpersincludesclasswporgnotificationsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/includes/class-wporg-notifications.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/includes/class-wporg-notifications.php    2022-09-14 16:56:00 UTC (rev 12062)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/includes/class-wporg-notifications.php      2022-09-15 15:13:17 UTC (rev 12063)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -325,6 +325,19 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                $output .= '- <strong>' . esc_html__( 'Translation string: ' ) . '</strong>' . esc_html( $translation->translation_0 ) . '<br>';
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                if ( isset( $comment_meta['reject_reason'][0] ) && ! empty( maybe_unserialize( $comment_meta['reject_reason'][0] ) ) ) {
+                       $reasons         = array();
+                       $comment_reasons = Helper_Translation_Discussion::get_comment_reasons();
+                       $reasons         = array_map(
+                               function( $reason ) use ( $comment_reasons ) {
+                                       if ( array_key_exists( $reason, $comment_reasons ) ) {
+                                               return $comment_reasons[ $reason ]['name'];
+                                       }
+                               },
+                               maybe_unserialize( $comment_meta['reject_reason'][0] )
+                       );
+                       $output         .= '- <strong>' . esc_html__( 'Reason(s): ' ) . '</strong>' . esc_html( implode( ', ', $reasons ) ) . '<br>';
+               }
</ins><span class="cx" style="display: block; padding: 0 10px">                 $output .= '- <strong>' . esc_html__( 'Comment: ' ) . '</strong>' . esc_html( $comment->comment_content ) . '</pre>';
</span><span class="cx" style="display: block; padding: 0 10px">                $output .= '<br><br>';
</span><span class="cx" style="display: block; padding: 0 10px">                $output .= esc_html__( 'Have a nice day' );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -429,12 +442,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return array The list of emails with the opt-in enabled.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        private static function get_opted_in_email_addresses( array $email_addresses ): array {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                foreach ( $email_addresses as $email_address ) {
-                       if ( self::is_global_optout_email_address( $email_address ) ) {
-                               $index = array_search( $email_address, $email_addresses, true );
-                               if ( false !== $index ) {
-                                       unset( $email_addresses[ $index ] );
-                               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         foreach ( $email_addresses as $index => $email_address ) {
+                       if ( ! is_string( $email_address ) || empty( $email_address ) || self::is_global_optout_email_address( $email_address ) ) {
+                               unset( $email_addresses[ $index ] );
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">                return array_values( $email_addresses );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -450,6 +460,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @return bool Whether a user wis globally opt-out.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        private static function is_global_optout_email_address( string $email_address ): bool {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                if ( empty( $email_address ) || ! is_email( $email_address ) ) {
+                       return false;
+               }
</ins><span class="cx" style="display: block; padding: 0 10px">                 $user            = get_user_by( 'email', $email_address );
</span><span class="cx" style="display: block; padding: 0 10px">                $gp_default_sort = get_user_option( 'gp_default_sort', $user->ID );
</span><span class="cx" style="display: block; padding: 0 10px">                if ( 'on' != gp_array_get( $gp_default_sort, 'notifications_optin', 'off' ) ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -601,8 +614,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">        public static function optin_message_for_each_discussion( int $original_id ): string {
</span><span class="cx" style="display: block; padding: 0 10px">                $user = wp_get_current_user();
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                if ( ! $user->user_email ) {
+                       return __( "You will not receive notifications because you don't have an e-mail address set." );
+               }
</ins><span class="cx" style="display: block; padding: 0 10px">                 if ( self::is_global_optout_email_address( $user->user_email ) ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $output  = __( 'You will not receive notifications because you have not yet opted-in. ' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $output  = __( 'You will not receive notifications because you have not yet opted-in.' );
</ins><span class="cx" style="display: block; padding: 0 10px">                         $output .= ' <a href="https://translate.wordpress.org/settings/">' . __( 'Start receiving notifications.' ) . '</a>';
</span><span class="cx" style="display: block; padding: 0 10px">                        return $output;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span></span></pre></div>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsgptranslationhelpersjsrejectfeedbackjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/js/reject-feedback.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/js/reject-feedback.js     2022-09-14 16:56:00 UTC (rev 12062)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/js/reject-feedback.js       2022-09-15 15:13:17 UTC (rev 12063)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,4 +1,4 @@
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/* global $gp, $gp_comment_feedback_settings, document, tb_show */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/* global $gp, $gp_comment_feedback_settings, document, tb_show, console */
</ins><span class="cx" style="display: block; padding: 0 10px"> ( function( $, $gp ) {
</span><span class="cx" style="display: block; padding: 0 10px">        $( document ).ready(
</span><span class="cx" style="display: block; padding: 0 10px">                function() {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -15,6 +15,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        '<textarea name="modal_feedback_comment"></textarea>' +
</span><span class="cx" style="display: block; padding: 0 10px">                        '</div>' +
</span><span class="cx" style="display: block; padding: 0 10px">                        '<button id="modal-reject-btn" class="modal-btn gp-btn-style">Reject</button>' +
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        '<button id="modal-requestchanges-btn" class="modal-btn gp-btn-style" style="display: none;" class="modal-btn">Request changes</button>' +
</ins><span class="cx" style="display: block; padding: 0 10px">                         '</form>' +
</span><span class="cx" style="display: block; padding: 0 10px">                        '</div>';
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -23,7 +24,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        // Remove click event added to <summary> by wporg-gp-customizations plugin
</span><span class="cx" style="display: block; padding: 0 10px">                        $( $gp.editor.table ).off( 'click', 'summary' );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $( '#bulk-actions-toolbar-top .button, #bulk-actions-toolbar .button' ).click( function( e ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $( '#bulk-actions-toolbar-top .button, #bulk-actions-toolbar-bottom .button' ).click( function( e ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 rowIds = $( 'input:checked', $( 'table#translations th.checkbox' ) ).map( function() {
</span><span class="cx" style="display: block; padding: 0 10px">                                        var selectedRow = $( this ).parents( 'tr.preview' );
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ( ! selectedRow.hasClass( 'untranslated' ) ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -56,7 +57,21 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="cx" style="display: block; padding: 0 10px">                        } );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $( 'body' ).on( 'click', '#modal-reject-btn', function( e ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 /**
+                        * Changes the value for the rejected status in the top toolbar to "changes requested"
+                        *
+                        * @param {Object} thisObj The object that dispatches this call.
+                        */
+                       function updateBulkRejectStatus( thisObj ) {
+                               var form = thisObj.closest( 'form' );
+                               var commentText = form.find( 'textarea[name="modal_feedback_comment"]' ).val();
+                               var numberOfCheckedReasons = form.find( 'input[name="modal_feedback_reason"]:checked' ).length;
+                               if ( commentText || numberOfCheckedReasons ) {
+                                       $( 'form#bulk-actions-toolbar-top  option[value="reject"]' ).attr( 'value', 'changesrequested' ).text( 'Changes requested' );
+                               }
+                       }
+
+                       $( 'body' ).on( 'click', '#modal-reject-btn, #modal-requestchanges-btn', function( e ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 var comment = '';
</span><span class="cx" style="display: block; padding: 0 10px">                                var commentReason = [];
</span><span class="cx" style="display: block; padding: 0 10px">                                var commentData = {};
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -69,7 +84,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                comment = form.find( 'textarea[name="modal_feedback_comment"]' ).val();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         updateBulkRejectStatus( $( this ) );
</ins><span class="cx" style="display: block; padding: 0 10px">                                 if ( ( ! comment.trim().length && ! commentReason.length ) || ( ! translationIds.length || ! originalIds.length ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        $( 'form.filters-toolbar.bulk-actions, form#bulk-actions-toolbar-top' ).submit();
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -84,6 +99,76 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                e.preventDefault();
</span><span class="cx" style="display: block; padding: 0 10px">                        } );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        $( '.feedback-reason-list' ).on( 'click', function( e ) {
+                               toggleButtons( $( this ), e );
+                       } );
+                       $( '.feedback-comment' ).on( 'input', function( e ) {
+                               toggleButtons( $( this ), e );
+                       } );
+
+                       /**
+                        * Hide and show one of each two buttons in the individual rejection: "Reject" and "Request changes".
+                        *
+                        * If the user has checked some reason or has entered some text in the textarea,
+                        * this function hides the "Reject" button and shows the "Request changes" one.
+                        * Otherwise, does the opposite.
+                        *
+                        * @param {Object}         thisObj The object that dispatches this call.
+                        * @param {document#event} event   The event.
+                        */
+                       function toggleButtons( thisObj, event ) {
+                               var form = thisObj.closest( 'form' );
+                               var commentText = form.find( 'textarea[name="feedback_comment"]' ).val();
+                               var div = thisObj.closest( '.meta' );
+                               var rejectButton = $( '.reject', div );
+                               var changesRequestedtButton = $( '.changesrequested', div );
+                               var numberOfCheckedReasons = form.find( 'input[name="feedback_reason"]:checked' ).length;
+
+                               if ( commentText.trim() !== '' || numberOfCheckedReasons ) {
+                                       rejectButton.hide();
+                                       changesRequestedtButton.show();
+                               } else {
+                                       rejectButton.show();
+                                       changesRequestedtButton.hide();
+                               }
+                               event.stopImmediatePropagation();
+                       }
+
+                       $( '.modal-item' ).on( 'click', function( e ) {
+                               toggleModalButtons( $( this ), e );
+                       } );
+                       $( 'textarea[name="modal_feedback_comment"]' ).on( 'input', function( e ) {
+                               toggleModalButtons( $( this ), e );
+                       } );
+
+                       /**
+                        * Hide and show one of each two buttons in the reject modal: "Reject" and "Request changes".
+                        *
+                        * In the modal, if the user has checked some reason or has entered some text in the textarea,
+                        * this function hides the "Reject" button and shows the "Request changes" one.
+                        * Otherwise, does the opposite.
+                        *
+                        * @param {Object}         thisObj The object that dispatches this call.
+                        * @param {document#event} event   The event.
+                        */
+                       function toggleModalButtons( thisObj, event ) {
+                               var form = thisObj.closest( 'form' );
+                               var commentText = form.find( 'textarea[name="modal_feedback_comment"]' ).val();
+                               var div = thisObj.closest( '#TB_ajaxContent' );
+                               var rejectButton = $( '#modal-reject-btn', div );
+                               var changesRequestedtButton = $( '#modal-requestchanges-btn', div );
+                               var numberOfCheckedReasons = form.find( 'input[name="modal_feedback_reason"]:checked' ).length;
+
+                               if ( commentText.trim() !== '' || numberOfCheckedReasons ) {
+                                       rejectButton.hide();
+                                       changesRequestedtButton.show();
+                               } else {
+                                       rejectButton.show();
+                                       changesRequestedtButton.hide();
+                               }
+                               event.stopImmediatePropagation();
+                       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                         $( '.tooltip' ).tooltip( {
</span><span class="cx" style="display: block; padding: 0 10px">                                tooltipClass: 'hoverTooltip',
</span><span class="cx" style="display: block; padding: 0 10px">                        } );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -102,6 +187,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                setStatus( $( this ), 'rejected' );
</span><span class="cx" style="display: block; padding: 0 10px">        };
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        $gp.editor.hooks.set_status_changesrequested = function() {
+               setStatus( $( this ), 'changesrequested' );
+       };
+
</ins><span class="cx" style="display: block; padding: 0 10px">         function setStatus( that, status ) {
</span><span class="cx" style="display: block; padding: 0 10px">                var button = $( that );
</span><span class="cx" style="display: block; padding: 0 10px">                var feedbackData = {};
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -164,11 +253,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                ).fail(
</span><span class="cx" style="display: block; padding: 0 10px">                        function( xhr, msg ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                /* eslint no-console: ["error", { allow: ["error"] }] */
+                               console.error( data );
</ins><span class="cx" style="display: block; padding: 0 10px">                                 msg = 'An error has occurred';
</span><span class="cx" style="display: block; padding: 0 10px">                                if ( xhr.responseText ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        msg += ': ' + xhr.responseText;
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                msg += '. Please, take a screenshot, send it to the developers, and reload the page to see if it still worked.';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         msg += '. Please, take a screenshot of the output in the browser console, send it to the developers, and reload the page to see if it works.';
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $gp.notices.error( msg );
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span></span></pre></div>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsgptranslationhelperstemplatesdiscussionsdashboardphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/templates/discussions-dashboard.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/templates/discussions-dashboard.php                               (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/templates/discussions-dashboard.php 2022-09-15 15:13:17 UTC (rev 12063)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,231 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+gp_title( __( 'Translation status overview &lt; GlotPress' ) );
+gp_enqueue_script( 'tablesorter' );
+
+$breadcrumb   = array();
+$breadcrumb[] = gp_link_get( '/', __( 'Locales' ) );
+$breadcrumb[] = gp_link_get( gp_url_join( '/locale', $locale_slug ), esc_html( $gp_locale->english_name ) );
+$breadcrumb[] = 'Discussions';
+gp_breadcrumb( $breadcrumb );
+gp_tmpl_header();
+
+?>
+<style>
+       html { scroll-behavior: smooth; }
+       table td { overflow-wrap: break-word }
+</style>
+
+<?php
+if ( ! $comments ) {
+       echo 'There are no discussions in this locale';
+       return;
+}
+
+$comments_by_post_id            = array();
+$bulk_comments                  = array();
+$latest_comment_date_by_post_id = array();
+
+foreach ( $comments as $_comment ) {
+       $is_linking_comment = preg_match( '!^' . home_url( gp_url() ) . '[a-z0-9_/#-]+$!i', $_comment->comment_content );
+       if ( $is_linking_comment ) {
+               $linked_comment = $_comment->comment_content;
+               $parts          = wp_parse_url( $linked_comment );
+               $parts['path']  = rtrim( $parts['path'], '/' );
+               $parts['path']  = rtrim( $parts['path'], '/' );
+               $path_parts     = explode( '/', $parts['path'] );
+
+               $linking_comment_original_id = array_pop( $path_parts );
+
+               if ( ! isset( $bulk_comments[ $linking_comment_original_id ] ) ) {
+                       $bulk_comments[ $linking_comment_original_id ] = array();
+               }
+
+               $bulk_comments[ $linking_comment_original_id ][] = $_comment;
+               continue;
+       }
+
+       if ( ! isset( $comments_by_post_id[ $_comment->comment_post_ID ] ) ) {
+               $comments_by_post_id[ $_comment->comment_post_ID ] = array();
+       }
+
+
+       $comments_by_post_id[ $_comment->comment_post_ID ][] = $_comment;
+
+       if ( ! isset( $latest_comment_date_by_post_id[ $_comment->comment_post_ID ] ) ) {
+               $latest_comment_date_by_post_id[ $_comment->comment_post_ID ] = $_comment->comment_date;
+       } elseif ( $latest_comment_date_by_post_id[ $_comment->comment_post_ID ] < $_comment->comment_date ) {
+               $latest_comment_date_by_post_id[ $_comment->comment_post_ID ] = $_comment->comment_date;
+       }
+}
+
+// If the referenced comment is not in the current batch of comments we need to re-add it.
+foreach ( $bulk_comments as $original_id => $_post_id ) {
+       if ( ! isset( $comments_by_post_id[ $_comment->comment_post_ID ] ) ) {
+               $linked_comment = $_comment->comment_content;
+               $parts          = wp_parse_url( $linked_comment );
+               $comment_id     = intval( str_replace( 'comment-', '', $parts['fragment'] ) );
+               if ( $comment_id ) {
+                       $comments_by_post_id[ $_comment->comment_post_ID ][] = get_comment( $comment_id );
+               }
+       }
+}
+
+uasort(
+       $comments_by_post_id,
+       function( $a, $b ) use ( $latest_comment_date_by_post_id ) {
+               return $latest_comment_date_by_post_id[ $b->comment_post_ID ] <=> $latest_comment_date_by_post_id[ $a->comment_post_ID ];
+       }
+);
+
+$args = array(
+       'style'            => 'ul',
+       'type'             => 'comment',
+       'callback'         => 'gth_discussion_callback',
+       'reverse_children' => false,
+);
+
+
+
+?>
+
+<table id="translations" class="translations clear">
+       <thead class="discussions-table-head">
+       <tr>
+               <th>Original string</th>
+               <th>Comment</th>
+               <th>Project</th>
+               <th>Author</th>
+               <th>Submitted on</th>
+       </tr>
+       </thead>
+       <tbody>
+               <?php
+               foreach ( $comments_by_post_id as $_post_id => $post_comments ) {
+                       $original_id = Helper_Translation_Discussion::get_original_from_post_id( $_post_id );
+                       if ( ! $original_id ) {
+                               continue;
+                       }
+
+                       $original       = GP::$original->get( $original_id );
+                       $project        = GP::$project->get( $original->project_id );
+                       $parent_project = GP::$project->get( $project->parent_project_id );
+                       $project_name   = ( $parent_project ) ? $parent_project->name : $project->name;
+                       $project_link   = gp_link_project_get( $project, esc_html( $project_name ) );
+
+                       $first_comment        = reset( $post_comments );
+                       $no_of_other_comments = count( $post_comments ) - 1;
+                       $_translation_set     = GP::$translation_set->by_project_id( $project->id );
+                       $comment_link         = get_permalink( $first_comment->comment_post_ID ) . $locale_slug . '/' . $_translation_set[0]->slug . '/#comment-' . $first_comment->comment_ID;
+                       $original_permalink   = gp_url_project_locale(
+                               $project,
+                               $locale_slug,
+                               $_translation_set[0]->slug,
+                               array(
+                                       'filters[original_id]' => $original_id,
+                                       'filters[status]'      => 'either',
+                               )
+                       );
+
+                       ?>
+                       <tr>
+                               <td>
+                               <a href="<?php echo esc_url( $original_permalink ); ?>">
+                                       <?php echo esc_html( $original->singular ); ?>
+                               </a>
+                                               <?php if ( isset( $bulk_comments[ $original_id ] ) ) { ?>
+                                               <details>
+                                                       <summary class="other-comments">
+                                                       <?php
+                                                       /* translators: number of other originals in the bulk rejection. */
+                                                       printf( '+ ' . _n( 'Thread with %s comment', 'Thread with %s comments', count( $bulk_comments[ $original_id ] ) ), number_format_i18n( count( $bulk_comments[ $original_id ] ) ) );
+                                                       ?>
+                                               </summary>
+                                               <ul>
+                                                       <?php
+                                                       foreach ( $bulk_comments[ $original_id ] as $_comment ) {
+                                                               $bulk_link_text = $_comment->comment_content;
+                                                               $_original_id   = Helper_Translation_Discussion::get_original_from_post_id( $_comment->comment_post_ID );
+                                                               if ( $_original_id ) {
+                                                                       $_original      = GP::$original->get( $_original_id );
+                                                                       $bulk_link_text = $_original->singular;
+                                                               }
+
+                                                               ?>
+                                                       <li class="bulk-comment-item"><a href="<?php echo esc_attr( $_comment->comment_content ); ?>"><?php echo esc_html( $bulk_link_text ); ?></a></li>
+                                                               <?php
+                                                       }
+                                                       ?>
+                                               </ul>
+                                               </details>
+                                                       <?php
+                                               }
+                                               ?>
+                               </td>
+                                <td>
+                                        <?php
+                                               if ( ! $first_comment->comment_content ) :
+                                                       ?>
+                                               
+                                                          <?php
+                                                               $comment_reason       = get_comment_meta( $first_comment->comment_ID, 'reject_reason', true );
+                                                               $number_of_items      = count( $comment_reason );
+                                                               $counter              = 0;
+                                                               $all_comment_reasons  = Helper_Translation_Discussion::get_comment_reasons();
+                                                               $comment_reasons_text = '';
+                                                               foreach ( $comment_reason as $reason ) {
+                                                                       $comment_reasons_text .= $all_comment_reasons[ $reason ]['name'];
+                                                                       if ( ++$counter < $number_of_items ) {
+                                                                                $comment_reasons_text .= ', ';
+                                                                       }
+                                                               }
+                                                               ?>
+                                                       <a href="<?php echo esc_url( $comment_link ); ?>"><?php echo esc_html( $comment_reasons_text ); ?></a>
+                                               
+                                          <?php else : ?>
+                                               <a href="<?php echo esc_url( $comment_link ); ?>"><?php echo esc_html( get_comment_excerpt( $first_comment ) ); ?></a>
+                                                  <?php if ( $no_of_other_comments > 0 ) : ?>
+                                                       <br>
+                                                               <?php /* translators: number of comments. */ ?>
+                                                       <a class="other-comments" href="<?php echo esc_url( $comment_link ); ?>"> + <?php printf( _n( '%s Comment', '%s Comments', $no_of_other_comments ), number_format_i18n( $no_of_other_comments ) ); ?></a>
+                                               <?php endif; ?>
+                                       <?php endif; ?>
+                               </td>
+                               <td><?php echo wp_kses( $project_link, array( 'a' => array( 'href' => true ) ) ); ?></td>
+                               <td><?php echo get_comment_author_link( $first_comment ); ?></td>
+                               <td><?php echo esc_html( $first_comment->comment_date ); ?></td>
+                       </tr>
+                       <?php
+               }
+               ?>
+               
+       </tbody>
+       
+</table>
+<?php
+       $current_page = max( 1, get_query_var( 'page' ) );
+       echo wp_kses(
+               paginate_links(
+                       array(
+                               'base'      => add_query_arg( 'page', '%#%' ),
+                               'format'    => '?page=%#%',
+                               'current'   => $current_page,
+                               'total'     => $total_pages,
+                               'prev_text' => __( '« prev' ),
+                               'next_text' => __( 'next Â»' ),
+                       )
+               ),
+               array(
+                       'span' => array(),
+                       'a'    => array(
+                               'href'  => array(),
+                               'class' => array(),
+                       ),
+               )
+       );
+
+       ?>
+
+       </li>
+</ul>
+<?php
+gp_tmpl_footer();
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/templates/discussions-dashboard.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsgptranslationhelperstemplatesgptemplatesoverrideslocaleprojectsphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/templates/gp-templates-overrides/locale-projects.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/templates/gp-templates-overrides/locale-projects.php                              (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/templates/gp-templates-overrides/locale-projects.php        2022-09-15 15:13:17 UTC (rev 12063)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,318 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * This template overrides the default local-projects template so we can add a link to "Discussions" dashboard.
+ *
+ * Todo: Remove this template override and add customizations directly in wporg-gp-customizations plugin.
+ */
+
+/* translators: %s: locale */
+gp_title( sprintf( __( 'Projects translated to %s &lt; GlotPress' ), esc_html( $locale->english_name ) ) );
+
+$breadcrumb   = array();
+$breadcrumb[] = gp_link_get( '/', __( 'Locales' ) );
+$breadcrumb[] = gp_link_get( gp_url_join( '/locale', $locale_slug, $set_slug ), esc_html( $locale->english_name ) );
+$breadcrumb[] = esc_html( $project->name );
+gp_breadcrumb( $breadcrumb );
+gp_tmpl_header();
+?>
+
+<div class="locale-header">
+       <p class="locale-intro">Translate WordPress, core projects, plugins, and themes into your language. Select your project below to get started.</p>
+
+       <div class="locale-box">
+               <ul class="name">
+                       <li class="english"><?php echo esc_html( $locale->english_name ); ?></li>
+                       <li class="native"><?php echo esc_html( $locale->native_name ); ?></li>
+                       <li class="code">
+                               <?php
+                               echo esc_html( $locale->wp_locale );
+
+                               if ( count( $variants ) > 1 ) {
+                                       ?>
+                                       <select id="variant-selector" name="variant">
+                                               <?php
+                                               foreach ( $variants as $variant ) {
+                                                       $selected =
+                                                       printf(
+                                                               '<option name="%s" data-project-url="%s"%s>%s</option>',
+                                                               $variant,
+                                                               esc_url( gp_url_join( '/locale', $locale_slug, $variant, $project->slug ) ),
+                                                               ( $set_slug == $variant ) ? ' selected="selected"' : '',
+                                                               esc_html( ucfirst( $variant ) )
+                                                       );
+                                               }
+                                               ?>
+                                       </select>
+                                       <?php
+                               }
+                               ?>
+                       </li>
+                       <?php if ( $locale_glossary ) : ?>
+                               <li class="locale-glossary">
+                                       <a href="<?php echo esc_url( gp_url_join( gp_url( '/locale' ), $locale_slug, $set_slug, 'glossary' ) ); ?>" class="glossary-link"><?php _e( 'Locale Glossary', 'glotpress' ); ?></a>
+                               </li>
+                       <?php elseif ( $can_create_locale_glossary ) : ?>
+                               <li class="locale-glossary">
+                                       <a href="<?php echo esc_url( gp_url_join( gp_url( '/locale' ), $locale_slug, $set_slug, 'glossary' ) ); ?>" class="glossary-link"><?php _e( 'Create Locale Glossary', 'glotpress' ); ?></a>
+                               </li>
+                       <?php endif; ?>
+               </ul>
+               <div class="contributors">
+                       <?php
+                       $contributors = sprintf(
+                               '<span class="dashicons dashicons-admin-users"></span><br />%s',
+                               isset( $contributors_count[ $locale->slug ] ) ? $contributors_count[ $locale->slug ] : 0
+                       );
+                       echo gp_link_get( 'https://make.wordpress.org/polyglots/teams/?locale=' . $locale->wp_locale, $contributors );
+                       ?>
+               </div>
+       </div>
+</div>
+
+<div class="filter-header">
+       <ul class="filter-header-links">
+               <?php
+               foreach ( $top_level_projects as $top_level_project ) {
+                       printf(
+                               '<li><a href="%s"%s>%s</a></li>',
+                               esc_url( gp_url_join( '/locale', $locale_slug, $set_slug, $top_level_project->slug ) ),
+                               ( $top_level_project->path == $project_path ) ? ' class="current"' : '',
+                               esc_html( $top_level_project->name )
+                       );
+               }
+               ?>
+               <li class="filter-header-link__sep" aria-hidden="true">|</li>
+               <li class="has-children">
+                       <a href="#">Stats</a>
+                       <ul>
+                               <li><a href="<?php echo esc_url( gp_url_join( '/locale', $locale_slug, $set_slug, 'stats', 'plugins' ) ); ?>">Plugins</a></li>
+                               <li><a href="<?php echo esc_url( gp_url_join( '/locale', $locale_slug, $set_slug, 'stats', 'themes' ) ); ?>">Themes</a></li>
+                       </ul>
+               </li>
+       <?php
+       /**
+        * Apply same logic that show the waiting tab to the discussions tab,
+        * so that this tab is only visible to global admins and GTEs/PTEs.
+        *
+        * Todo: Modify this logic mentioned above so that here can use something like $is_admin_or_gte?
+        */
+       if ( is_user_logged_in() && 'waiting' === $default_project_tab ) :
+               ?>
+               <li><a href="<?php echo esc_url( gp_url_join( '/locale', $locale_slug, $set_slug, 'discussions' ) ); ?>">Discussions</a></li>
+       <?php endif ?>
+               </ul>
+       <div class="search-form">
+               <form>
+                       <label class="screen-reader-text" for="projects-filter"><?php esc_attr_e( 'Search projects...' ); ?></label>
+                       <input placeholder="<?php esc_attr_e( 'Search projects...' ); ?>" type="search" id="projects-filter" name="s" value="
+                                                                                                 <?php
+                                                                                                       if ( ! empty( $search ) ) {
+                                                                                                               echo esc_attr( $search ); }
+                                                                                                       ?>
+                       " class="filter-search">
+                       <input type="submit" value="<?php esc_attr_e( 'Search' ); ?>" class="screen-reader-text" />
+               </form>
+       </div>
+</div>
+<div class="sort-bar">
+       <form id="sort-filter" action="" method="GET">
+               <input type="hidden" name="s" value="<?php echo esc_attr( $search ?? '' ); ?>"
+               <input type="hidden" name="page" value="1">
+
+               <?php
+               $filter_count = 0;
+
+               if ( 'waiting' === $project->slug && is_user_logged_in() ) {
+                       $filter_count++;
+                       ?>
+                       <input id="filter-without-editors" type="checkbox" name="without-editors" value="1"<?php checked( isset( $_GET['without-editors'] ) ); ?>>
+                       <label for="filter-without-editors">Limit to projects without editors</label>
+                       <span class="filter-sep" aria-hidden="true">|</span>
+                       <?php
+               }
+               ?>
+
+               <?php
+               $filter_count++;
+               ?>
+               <label for="filter">Filter:</label>
+               <select id="filter" name="filter">
+                       <?php
+                               $sorts = array();
+                       if ( is_user_logged_in() && in_array( $project->slug, array( 'waiting', 'wp-themes', 'wp-plugins' ) ) ) {
+                               $sorts['special']   = 'Untranslated Favorites, Remaining Strings (Most first)';
+                               $sorts['favorites'] = 'My Favorites';
+                       }
+                               $sorts['strings-remaining']                              = 'Remaining Strings (Most first)';
+                               $sorts['strings-remaining-asc']                          = 'Remaining Strings (Least first)';
+                               $sorts['strings-waiting-and-fuzzy']                      = 'Waiting + Fuzzy (Most first)';
+                               $sorts['strings-waiting-and-fuzzy-asc']                  = 'Waiting + Fuzzy (Least first)';
+                               $sorts['strings-waiting-and-fuzzy-by-modified-date']     = 'Waiting + Fuzzy (Newest first)';
+                               $sorts['strings-waiting-and-fuzzy-by-modified-date-asc'] = 'Waiting + Fuzzy (Oldest first)';
+                               $sorts['percent-completed']                              = 'Percent Completed (Most first)';
+                               $sorts['percent-completed-asc']                          = 'Percent Completed (Least first)';
+
+                               // Completed project filter, except on the 'waiting' project.
+                       if ( 'waiting' !== $project->slug ) {
+                               $sorts['completed-asc'] = '100% Translations';
+                       }
+
+                       foreach ( $sorts as $value => $text ) {
+                               printf( '<option value="%s" %s>%s</option>', esc_attr( $value ), ( $value == $filter ? 'selected="selected"' : '' ), esc_attr( $text ) );
+                       }
+                       ?>
+               </select>
+
+               <button type="submit"><?php echo ( 1 === $filter_count ? 'Apply Filter' : 'Apply Filters' ); ?></button>
+       </form>
+</div>
+<div id="projects" class="projects">
+       <?php
+       foreach ( $sub_projects as $sub_project ) {
+               $percent_complete = $waiting = $sub_projects_count = $fuzzy = $remaining = 0;
+               if ( isset( $project_status[ $sub_project->id ] ) ) {
+                       $status_of_project  = $project_status[ $sub_project->id ];
+                       $percent_complete   = $status_of_project->percent_complete;
+                       $waiting            = $status_of_project->waiting_count;
+                       $fuzzy              = $status_of_project->fuzzy_count;
+                       $remaining          = $status_of_project->all_count - $status_of_project->current_count;
+                       $sub_projects_count = $status_of_project->sub_projects_count;
+               }
+
+               // Link directly to the Waiting strings if we're in the Waiting view, otherwise link to the project overview
+               if ( 'waiting' == $project->slug ) {
+                       // TODO: Since we're matching parent projects, we can't link to them as they have no direct translation sets.
+                       // $project_url = gp_url_join( '/projects', $sub_project->path, $locale_slug, $set_slug ) . '?filters[status]=waiting_or_fuzzy';
+                       $project_url = gp_url_join( '/locale', $locale_slug, $set_slug, $sub_project->path );
+
+                       $project_name      = $sub_project->name;
+                       $parent_project_id = $sub_project->parent_project_id;
+                       while ( $parent_project_id ) {
+                               $parent_project    = GP::$project->get( $parent_project_id );
+                               $parent_project_id = $parent_project->parent_project_id;
+                               $project_name      = "{$parent_project->name} - {$project_name}";
+                       }
+               } else {
+                       $project_url  = gp_url_join( '/locale', $locale_slug, $set_slug, $sub_project->path );
+                       $project_name = $sub_project->name;
+               }
+
+               $project_icon = '';
+               if ( isset( $project_icons[ $sub_project->id ] ) ) {
+                       $project_icon = $project_icons[ $sub_project->id ];
+               }
+
+               $classes  = 'project-' . sanitize_title_with_dashes( str_replace( '/', '-', $project->path ) );
+               $classes .= ' project-' . sanitize_title_with_dashes( str_replace( '/', '-', $sub_project->path ) );
+               $classes .= ' percent-' . $percent_complete;
+               ?>
+               <div class="project <?php echo esc_attr( $classes ); ?>">
+                       <div class="project-top">
+                               <div class="project-icon">
+                                       <?php echo gp_link_get( $project_url, $project_icon ); ?>
+                               </div>
+
+                               <div class="project-name">
+                                       <h4>
+                                               <?php echo gp_link_get( $project_url, $project_name ); ?>
+                                       </h4>
+                               </div>
+                               <div class="project-description">
+                                       <p>
+                                       <?php
+                                               $description = wp_strip_all_tags( $sub_project->description );
+                                               $description = str_replace( array( 'WordPress.org Plugin Page', 'WordPress.org Theme Page' ), '', $description );
+                                               echo esc_html( wp_trim_words( $description, 30 ) );
+                                       ?>
+                                       </p>
+                               </div>
+                       </div>
+
+                       <div class="project-status">
+                               <div class="project-status-sub-projects">
+                                       <span class="project-status-title">Projects</span>
+                                       <span class="project-status-value"><?php echo number_format_i18n( $sub_projects_count ); ?></span>
+                               </div>
+                               <div class="project-status-waiting">
+                                       <span class="project-status-title">Waiting/Fuzzy</span>
+                                       <span class="project-status-value"><?php echo number_format_i18n( $waiting + $fuzzy ); ?></span>
+                               </div>
+                               <div class="project-status-remaining">
+                                       <span class="project-status-title">Remaining</span>
+                                       <span class="project-status-value"><?php echo number_format_i18n( $remaining ); ?></span>
+                               </div>
+                               <div class="project-status-progress">
+                                       <span class="project-status-title">Progress</span>
+                                       <span class="project-status-value"><?php echo number_format_i18n( $percent_complete ); ?>%</span>
+                               </div>
+                       </div>
+
+                       <div class="percent">
+                               <div class="percent-complete" style="width:<?php echo esc_attr( $percent_complete ); ?>%;"></div>
+                       </div>
+
+                       <div class="project-bottom">
+                               <?php echo gp_link_get( $project_url, 'Translate Project', array( 'class' => 'button contribute-button' ) ); ?>
+                       </div>
+               </div>
+               <?php
+       }
+       if ( ! $sub_projects ) {
+               if ( 'waiting' === $project->slug ) {
+                       echo '<div class="no-projects-found">No projects with strings awaiting approval!</div>';
+               } else {
+                       echo '<div class="no-projects-found">No projects found.</div>';
+               }
+       }
+       ?>
+</div>
+<?php
+if ( isset( $pages ) && $pages['pages'] > 1 ) {
+       echo gp_pagination( $pages['page'], $pages['per_page'], $pages['results'] );
+}
+?>
+
+<script>
+       jQuery( document ).ready( function( $ ) {
+               // Don't filter if there's an existing search term, or if we're paginated
+               // Fall back to a full page reload for those cases.
+               var live_filtering_enabled = ( ! $( '#projects-filter' ).val() && ! $( '.paging' ).length );
+               $rows = $( '#projects' ).find( '.project' );
+               $( '#projects-filter' ).on( 'input keyup', function() {
+                       if ( ! live_filtering_enabled ) {
+                               return;
+                       }
+
+                       var words = this.value.toLowerCase().split( ' ' );
+
+                       if ( '' === this.value.trim() ) {
+                               $rows.show();
+                       } else {
+                               $rows.hide();
+                               $rows.filter( function( i, v ) {
+                                       var $t = $(this).find( '.project-top' );
+                                       for ( var d = 0; d < words.length; ++d ) {
+                                               if ( $t.text().toLowerCase().indexOf( words[d] ) != -1 ) {
+                                                       return true;
+                                               }
+                                       }
+                                       return false;
+                               }).show();
+                       }
+               });
+
+               $( '#variant-selector' ).on( 'change', function( event ) {
+                       event.preventDefault();
+
+                       var $optionSelected = $( 'option:selected', this ),
+                               projectUrl = $optionSelected.data( 'projectUrl' );
+
+                       if ( projectUrl.length ) {
+                               window.location = projectUrl;
+                       }
+               });
+       });
+</script>
+
+<?php
+gp_tmpl_footer();
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/templates/gp-templates-overrides/locale-projects.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsgptranslationhelperstemplatesgptemplatesoverridestranslationroweditormetastatusphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/templates/gp-templates-overrides/translation-row-editor-meta-status.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/templates/gp-templates-overrides/translation-row-editor-meta-status.php   2022-09-14 16:56:00 UTC (rev 12062)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/templates/gp-templates-overrides/translation-row-editor-meta-status.php     2022-09-15 15:13:17 UTC (rev 12063)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -19,6 +19,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                <?php endif; ?>
</span><span class="cx" style="display: block; padding: 0 10px">                                <?php if ( 'rejected' !== $translation->translation_status ) : ?>
</span><span class="cx" style="display: block; padding: 0 10px">                                        <button class="reject" data-nonce="<?php echo esc_attr( wp_create_nonce( 'update-translation-status-rejected_' . $translation->id ) ); ?>" title="<?php esc_attr_e( 'Reject this translation. The existing translation will be kept as part of the translation history.', 'glotpress' ); ?>"><strong>&minus;</strong> <?php _ex( 'Reject', 'Action', 'glotpress' ); ?></button>
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                        <button class="changesrequested" style="display: none;" data-nonce="<?php echo esc_attr( wp_create_nonce( 'update-translation-status-changesrequested_' . $translation->id ) ); ?>" title="<?php esc_attr_e( 'Request changes for this translation. The existing translation will be kept as part of the translation history.', 'glotpress' ); ?>"><strong>&minus;</strong> <?php _ex( 'Request changes', 'Action', 'glotpress' ); ?></button>
</ins><span class="cx" style="display: block; padding: 0 10px">                                 <?php endif; ?>
</span><span class="cx" style="display: block; padding: 0 10px">                                <?php if ( 'fuzzy' !== $translation->translation_status ) : ?>
</span><span class="cx" style="display: block; padding: 0 10px">                                        <button class="fuzzy" data-nonce="<?php echo esc_attr( wp_create_nonce( 'update-translation-status-fuzzy_' . $translation->id ) ); ?>" title="<?php esc_attr_e( 'Mark this translation as fuzzy for further review.', 'glotpress' ); ?>"><strong>~</strong> <?php _ex( 'Fuzzy', 'Action', 'glotpress' ); ?></button>
</span></span></pre></div>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsgptranslationhelperstemplatesoriginalpermalinkphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/templates/original-permalink.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/templates/original-permalink.php  2022-09-14 16:56:00 UTC (rev 12062)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/gp-translation-helpers/templates/original-permalink.php    2022-09-15 15:13:17 UTC (rev 12063)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -115,10 +115,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">        <p>
</span><span class="cx" style="display: block; padding: 0 10px">                <a href="<?php echo esc_url( $translate_url ); ?>"><?php esc_html_e( 'This string has no translation in this language.' ); ?></a>
</span><span class="cx" style="display: block; padding: 0 10px">        </p>
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-<?php else : ?>
-       <p>
-               <?php esc_html_e( 'This string has no translation in this language.' ); ?>
-       </p>
</del><span class="cx" style="display: block; padding: 0 10px"> <?php endif; ?>
</span><span class="cx" style="display: block; padding: 0 10px"> <div class="translations" row="<?php echo esc_attr( $row_id . ( $translation ? '-' . $translation->id : '' ) ); ?>" replytocom="<?php echo esc_attr( gp_get( 'replytocom' ) ); ?>" >
</span><span class="cx" style="display: block; padding: 0 10px"> <div class="translation-helpers">
</span></span></pre>
</div>
</div>

</body>
</html>