[DOC-CVS] [doc-base] master: Do not mark do-not-translate files not translated (#339)

[email protected] (alfsb via GitHub)
Newsgroups php.doc.cvs
Message-ID <[email protected]>
Author: alfsb (alfsb)
Committer: GitHub (web-flow)
Pusher: alfsb
Date: 2026-08-28T09:21:07-03:00

Commit: https://github.com/php/doc-base/commit/6cb6c0dfe2584bce8b20347b9c2628f4d5784189
Raw diff: https://github.com/php/doc-base/commit/6cb6c0dfe2584bce8b20347b9c2628f4d5784189.diff

Do not mark do-not-translate files not translated (#339)

* Do not mark do-not-translate files not translated
* Full do-not-translate support

Changed paths:
  M  scripts/translation/lib/RevcheckRun.php
  M  scripts/translation/lib/RevtagParser.php
  M  scripts/translation/lib/XmlUtil.php


Diff:

diff --git a/scripts/translation/lib/RevcheckRun.php b/scripts/translation/lib/RevcheckRun.php
index ecb0764542..4f6df5530b 100644
--- a/scripts/translation/lib/RevcheckRun.php
+++ b/scripts/translation/lib/RevcheckRun.php
@@ -85,12 +85,7 @@ private function calculateStatus()
             if ( $target == null )
             {
                 if ( RevcheckIgnore::byMark( "{$this->sourceDir}/{$source->file}" ) )
-                {
-                    $source->status = RevcheckStatus::DoNotTranslate;
-                    $this->filesDoNotTranslate[] = $source;
-                    $this->addData( $source , null );
                     continue;
-                }
 
                 $source->status = RevcheckStatus::Untranslated;
                 $this->filesUntranslated[] = $source;
@@ -98,12 +93,17 @@ private function calculateStatus()
                 continue;
             }
 
+            // Do not translate
+
+            if ( $target->revtag->doNotTranslate )
+            {
+                $source->status = RevcheckStatus::DoNotTranslate;
+                $this->filesDoNotTranslate[] = $source;
+                $this->addData( $source , null );
+                continue;
+            }
+
             // XmlBroken
-            //
-            // Checked before the revtag, as a file that does not parse is
-            // the more pressing problem. The revtag is still carried over:
-            // libxml recovers, so the comments are read even from a
-            // misaligned file, and an empty one has nothing to read anyway.
 
             if ( $target->xmlError != "" )
             {
diff --git a/scripts/translation/lib/RevtagParser.php b/scripts/translation/lib/RevtagParser.php
index d3770d163d..b0f3a681ad 100644
--- a/scripts/translation/lib/RevtagParser.php
+++ b/scripts/translation/lib/RevtagParser.php
@@ -1,21 +1,20 @@
-<?php
-/**
- *  +----------------------------------------------------------------------+
- *  | Copyright (c) 1997-2023 The PHP Group                                |
- *  +----------------------------------------------------------------------+
- *  | This source file is subject to version 3.01 of the PHP license,      |
- *  | that is bundled with this package in the file LICENSE, and is        |
- *  | available through the world-wide-web at the following url:           |
- *  | https://www.php.net/license/3_01.txt.                                |
- *  | If you did not receive a copy of the PHP license and are unable to   |
- *  | obtain it through the world-wide-web, please send a note to          |
- *  | [email protected], so we can mail you a copy immediately.              |
- *  +----------------------------------------------------------------------+
- *  | Authors:     André L F S Bacci <ae php.net>                          |
- *  +----------------------------------------------------------------------+
- *  | Description: Parse revision and credits from XML comments.           |
- *  +----------------------------------------------------------------------+
- */
+<?php /*
++----------------------------------------------------------------------+
+| Copyright (c) 1997-2026 The PHP Group                                |
++----------------------------------------------------------------------+
+| This source file is subject to version 3.01 of the PHP license,      |
+| that is bundled with this package in the file LICENSE, and is        |
+| available through the world-wide-web at the following url:           |
+| https://www.php.net/license/3_01.txt.                                |
+| If you did not receive a copy of the PHP license and are unable to   |
+| obtain it through the world-wide-web, please send a note to          |
+| [email protected], so we can mail you a copy immediately.              |
++----------------------------------------------------------------------+
+| Authors:     André L F S Bacci <ae php.net>                          |
++----------------------------------------------------------------------+
+| Description: Parse revision and credits from XML comments.           |
++----------------------------------------------------------------------+
+*/
 
 require_once __DIR__ . '/all.php';
 
@@ -26,6 +25,7 @@ class RevtagInfo
     public string $status = "";
     public string $credits = "";
     public array  $errors = [];
+    public bool   $doNotTranslate = false;
 }
 
 class RevtagParser
@@ -34,94 +34,163 @@ static function parseDir( string $lang , RevcheckFileList $list )
     {
         foreach( $list->iterator() as $entry )
         {
-            $entry->revtag = RevtagParser::parseFile( $lang . '/' . $entry->file );
+            $contents = file_get_contents( $lang . '/' . $entry->file );
 
-            // Files are parsed here anyway, so reuse the errors already
-            // collected by XmlUtil, instead of loading everything again.
-            //
-            // Everything is XML in principle. The exception is the entity
-            // files still written as DTD fragments, that never parse as
-            // standalone XML: they are not .xml and hold entity
-            // declarations. Only those few are read back to be told apart,
-            // while still hot in the OS cache.
-
-            if ( str_ends_with( $entry->file , '.xml' ) == false )
+            // Everything here should be XML. The exception is the old
+            // entities files still written as DTD fragments.
+
+            if ( str_ends_with( $entry->file , '.ent' ) )
+            if ( str_contains( $contents , '<!ENTITY' ) )
             {
-                $contents = file_get_contents( $lang . '/' . $entry->file );
-                if ( str_contains( $contents , '<!ENTITY' ) )
-                    continue;
+                $entry->revtag = RevtagParser::parseFullText( $contents );
+                continue;
             }
 
+            $entry->revtag = RevtagParser::parseXmlText( $contents );
+
+            // Files are parsed here anyway, so reuse the errors already
+            // collected by XmlUtil, instead of loading everything again.
+
             $error = XmlUtil::$lastErrors[0] ?? null;
             if ( $error != null )
-                $entry->xmlError = trim( $error->message ) . " [{$error->line},{$error->column}]";
+                $entry->xmlError = trim( $error->message ) . " [{$error->line}:{$error->column}]";
         }
     }
 
-    public static function parseFile( string $filename ): RevtagInfo|null
+    public static function parseXmlText( string $contents ) : RevtagInfo
     {
-        $doc = XmlUtil::loadFile( $filename );
         $ret = new RevtagInfo;
-        RevtagParser::parseNodeRecurse( $doc , $ret , $filename );
-        return $ret;
-    }
 
-    public static function parseText( string $contents ): RevtagInfo|null
-    {
         $doc = XmlUtil::loadText( $contents );
-        $ret = new RevtagInfo;
-        RevtagParser::parseNodeRecurse( $doc , $ret );
+        $xpath = new DOMXPath( $doc );
+
+        // Revtags in XML comments
+
+        $comments = $xpath->query( '//comment()' );
+        foreach( $comments as $comment )
+            RevtagParser::parseTagText( $comment->textContent , $ret );
+
+        // do-not-translate mark in processing instructions
+
+        $marks = $xpath->query( '//processing-instruction()' );
+        foreach( $marks as $mark )
+            if ( $mark->target == 'do-not-translate' )
+                $ret->doNotTranslate = true;
+
         return $ret;
     }
 
-    public static function parseNodeRecurse( DOMNode $node , RevtagInfo $ret , $filename = "" )
+    public static function parseFullText( string $text ) : RevtagInfo
     {
-        if ( $node->nodeType == XML_COMMENT_NODE )
-            RevtagParser::parseComment( $node , $ret , $filename );
+        $ret = new RevtagInfo;
+
+        $match = [];
+        $regex = '/<!--.*?-->/';
+        preg_match_all( $regex , $text , $match );
 
-        foreach( $node->childNodes as $child )
-            RevtagParser::parseNodeRecurse( $child , $ret , $filename );
+        foreach ( $match[0] as $comment )
+            RevtagParser::parseTagText( $comment , $ret );
+
+        return $ret;
     }
 
-    public static function parseComment( DOMNode $node , RevtagInfo $ret , $filename = "" )
+    public static function parseTagText( string $text , RevtagInfo $ret )
     {
-        $text = trim( $node->textContent );
+        // /EN-Revision:\s*(\S+)\s*Maintainer:\s*(\S+)\s*Status:\s*(\S+)/       // restrict maintainer without spaces
+        // /EN-Revision:\s*(\S+)\s*Maintainer:\s(.*?)\sStatus:\s*(\S+)/         // accepts maintainer with spaces
 
-        if ( str_starts_with( $text , "EN-" ) )
+        $match = [];
+        $regex = "/EN-Revision:\s*(\S+)\s*Maintainer:\s(.*?)\sStatus:\s*(\S+)/";
+        if ( preg_match( $regex , $text , $match ) )
         {
-            // /EN-Revision:\s*(\S+)\s*Maintainer:\s*(\S+)\s*Status:\s*(\S+)/       // restrict maintainer without spaces
-            // /EN-Revision:\s*(\S+)\s*Maintainer:\s(.*?)\sStatus:\s*(\S+)/         // accepts maintainer with spaces
-
-            $match = [];
-            $regex = "/EN-Revision:\s*(\S+)\s*Maintainer:\s(.*?)\sStatus:\s*(\S+)/";
-            if ( preg_match( $regex , $text , $match ) )
-            {
-                $ret->revision = trim( $match[1] );
-                $ret->maintainer = trim( $match[2] );
-                $ret->status = trim( $match[3] );
-
-                if ( $ret->revision != "" && strlen( $ret->revision ) != 40 )
-                    $ret->errors[] = "Wrong hash size: {$ret->revision}";
-                if ( $ret->maintainer == "" )
-                    $ret->errors[] = "Empty maintainer.";
-                if ( $ret->status == "" )
-                    $ret->errors[] = "Empty status.";
-            }
-            else
-                $ret->errors[] = "No revtag.";
+            $ret->revision = trim( $match[1] );
+            $ret->maintainer = trim( $match[2] );
+            $ret->status = trim( $match[3] );
+
+            if ( $ret->revision != "" && strlen( $ret->revision ) != 40 )
+                $ret->errors[] = "Wrong hash size: {$ret->revision}";
+            if ( $ret->maintainer == "" )
+                $ret->errors[] = "Empty maintainer.";
+            if ( $ret->status == "" )
+                $ret->errors[] = "Empty status.";
         }
 
-        if ( str_starts_with( $text , "CREDITS:" ) )
+        $match = [];
+        $regex = "/CREDITS:(.*)/";
+        if ( preg_match( $regex , $text , $match ) )
         {
-            $match = [];
-            $regex = "/CREDITS:(.*)/";
-            if ( preg_match( $regex , $text , $match ) )
-            {
-                $ret->credits = trim( $match[1] );
+            $ret->credits = trim( $match[1] );
 
-                if ( $ret->credits == "" )
-                    $ret->errors[] = "Empty credits.";
-            }
+            if ( $ret->credits == "" )
+                $ret->errors[] = "Empty credits.";
         }
     }
+
+    // public static function parseFile( string $filename ): RevtagInfo|null
+    // {
+    //     $doc = XmlUtil::loadFile( $filename );
+    //     $ret = new RevtagInfo;
+    //     RevtagParser::parseNodeRecurse( $doc , $ret , $filename );
+    //     return $ret;
+    // }
+
+    // public static function parseText( string $contents ): RevtagInfo|null
+    // {
+    //     $doc = XmlUtil::loadText( $contents );
+    //     $ret = new RevtagInfo;
+    //     RevtagParser::parseNodeRecurse( $doc , $ret );
+    //     return $ret;
+    // }
+
+    // public static function parseNodeRecurse( DOMNode $node , RevtagInfo $ret , $filename = "" )
+    // {
+    //     if ( $node->nodeType == XML_COMMENT_NODE )
+    //         RevtagParser::parseComment( $node , $ret , $filename );
+
+    //     foreach( $node->childNodes as $child )
+    //         RevtagParser::parseNodeRecurse( $child , $ret , $filename );
+    // }
+
+    // public static function parseComment( DOMNode $node , RevtagInfo $ret , $filename = "" )
+    // {
+    //     $text = trim( $node->textContent );
+
+    //     if ( str_starts_with( $text , "EN-" ) )
+    //     {
+    //         // /EN-Revision:\s*(\S+)\s*Maintainer:\s*(\S+)\s*Status:\s*(\S+)/       // restrict maintainer without spaces
+    //         // /EN-Revision:\s*(\S+)\s*Maintainer:\s(.*?)\sStatus:\s*(\S+)/         // accepts maintainer with spaces
+
+    //         $match = [];
+    //         $regex = "/EN-Revision:\s*(\S+)\s*Maintainer:\s(.*?)\sStatus:\s*(\S+)/";
+    //         if ( preg_match( $regex , $text , $match ) )
+    //         {
+    //             $ret->revision = trim( $match[1] );
+    //             $ret->maintainer = trim( $match[2] );
+    //             $ret->status = trim( $match[3] );
+
+    //             if ( $ret->revision != "" && strlen( $ret->revision ) != 40 )
+    //                 $ret->errors[] = "Wrong hash size: {$ret->revision}";
+    //             if ( $ret->maintainer == "" )
+    //                 $ret->errors[] = "Empty maintainer.";
+    //             if ( $ret->status == "" )
+    //                 $ret->errors[] = "Empty status.";
+    //         }
+    //         else
+    //             $ret->errors[] = "No revtag.";
+    //     }
+
+    //     if ( str_starts_with( $text , "CREDITS:" ) )
+    //     {
+    //         $match = [];
+    //         $regex = "/CREDITS:(.*)/";
+    //         if ( preg_match( $regex , $text , $match ) )
+    //         {
+    //             $ret->credits = trim( $match[1] );
+
+    //             if ( $ret->credits == "" )
+    //                 $ret->errors[] = "Empty credits.";
+    //         }
+    //     }
+    // }
+
 }
diff --git a/scripts/translation/lib/XmlUtil.php b/scripts/translation/lib/XmlUtil.php
index 5eab7e26b0..0ddd04e459 100644
--- a/scripts/translation/lib/XmlUtil.php
+++ b/scripts/translation/lib/XmlUtil.php
@@ -21,7 +21,7 @@
 
 class XmlUtil
 {
-    /** Real errors of the last loadText(), undefined entities already filtered out. */
+    // Errors of the last loadText(), undefined entities already filtered out.
     public static array $lastErrors = [];
 
     public static function extractEntities( $filename )
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.