From 5741dbb6046f87c013752eff0aa9e9511e39ea02 Mon Sep 17 00:00:00 2001 From: Benjamin Renard Date: Wed, 22 Nov 2023 12:46:07 +0100 Subject: [PATCH] I18n: add extract_messages_excluded_paths parameter --- example/includes/core.php | 9 ++- src/App.php | 16 +++++ src/I18n.php | 126 +++++++++++++++++++++++++++----------- 3 files changed, 111 insertions(+), 40 deletions(-) diff --git a/example/includes/core.php b/example/includes/core.php index 9940b31..8843155 100644 --- a/example/includes/core.php +++ b/example/includes/core.php @@ -39,11 +39,14 @@ App::init( "$root_dir_path/static" ), ), + 'i18n' => array( + 'default_locale' => "en_US.UTF8", + 'extract_messages_excluded_paths' => array( + "static/lib" + ), + ), 'default' => array( 'upload_max_filesize' => 10485760, - 'i18n' => array( - 'default_locale' => "en_US.UTF8", - ), ), ), $root_dir_path diff --git a/src/App.php b/src/App.php index c888338..9070b81 100644 --- a/src/App.php +++ b/src/App.php @@ -254,4 +254,20 @@ class App { echo "

".I18n::_("You are now disconnected.")."

"; } + /** + * Helper method to resolve a given path if need and make it relative + * to application root directory + * @param string|null $path The path to handle (optional, default: current directory) + * @return string|false The relative path if exist and in app directory, absolute path if not in + * app directory or false if not exists. + */ + public static function relative_path($path=null) { + if (is_null($path)) $path = getcwd(); + $path = realpath($path); + if (!$path) return false; + if (strpos($path, self::root_directory_path()) !== 0) + return $path; + return substr($path, strlen(self::root_directory_path())+1); + } + } diff --git a/src/I18n.php b/src/I18n.php index 86a388e..5019a09 100644 --- a/src/I18n.php +++ b/src/I18n.php @@ -44,6 +44,7 @@ class I18n { array( 'root_directory' => '${root_directory_path}/locales', 'default_locale' => null, + 'extract_messages_excluded_paths' => ['.*/vendor/*'], ) ); @@ -452,17 +453,23 @@ class I18n { // Store list of generated POT files $pot_files = array(); + $root_directory_path = App::root_directory_path(); + $excluded_paths = App::get('i18n.extract_messages_excluded_paths', null, 'array'); + if (Cli::core_mode()) { // List EesyPHP PHP files to parse + $cmd = array( + 'find', '-name', "'*.php'", '-type', 'f', // Looking for PHP files + "-not", "-name", "'*.tpl.php'", // Exclude Smarty cache template files + ); + if ($excluded_paths) + foreach($excluded_paths as $path) + array_push($cmd, "-not", "-path", "'$path'"); $eesyphp_php_files = run_external_command( - array( - 'find', '-name', "'*.php'", // Looking for PHP files - "-not", "-path", "'.*/vendor/*'", // Exclude vendor directories - "-not", "-name", "'*.tpl.php'" // Exclude Smarty cache template files - ), - null, // no STDIN data - false, // do not escape command args (already done) - __DIR__ // Run from EesyPHP src directory + $cmd, + null, // no STDIN data + false, // do not escape command args (already done) + "$root_directory_path/src" // Run from EesyPHP src directory ); if (!is_array($eesyphp_php_files) || $eesyphp_php_files[0] != 0) Log :: fatal(self::_("Fail to list EesyPHP PHP files.")); @@ -474,15 +481,15 @@ class I18n { "xgettext", "--from-code utf-8", "--language=PHP", - "-o", $pot_file, // Output - "--omit-header", // No POT header - "--keyword=___", // Handle custom ___() translation function - "--files=-", // Read files to parse from STDIN - "--force-po", // Write PO file even if empty + "-o", $pot_file, // Output + "--omit-header", // No POT header + "--keyword=___", // Handle custom ___() translation function + "--files=-", // Read files to parse from STDIN + "--force-po", // Write PO file even if empty ), - $eesyphp_php_files[1], // Pass PHP files list via STDIN - true, // Escape parameters - __DIR__ // Run from EesyPHP src directory + $eesyphp_php_files[1], // Pass PHP files list via STDIN + true, // Escape parameters + "$root_directory_path/src" // Run from EesyPHP src directory ); if (!is_array($result) || $result[0] != 0) Log :: fatal(self::_("Fail to extract messages from EesyPHP PHP files using xgettext.")); @@ -491,15 +498,17 @@ class I18n { } else { // List application PHP files to parse + $cmd = array( + 'find', '-name', "'*.php'", '-type', 'f', // Looking for PHP files + "-not", "-name", "'*.tpl.php'", // Exclude Smarty cache template files + ); + foreach($excluded_paths as $path) + array_push($cmd, "-not", "-path", "'$path'"); $php_files = run_external_command( - array( - 'find', '-name', "'*.php'", // Looking for PHP files - "-not", "-path", "'.*/vendor/*'", // Exclude vendor directories - "-not", "-name", "'*.tpl.php'" // Exclude Smarty cache template files - ), - null, // no STDIN data - false, // do not escape command args (already done) - App :: root_directory_path() // Run from Application root directory + $cmd, + null, // no STDIN data + false, // do not escape command args (already done) + $root_directory_path // Run from application root directory ); if (!is_array($php_files) || $php_files[0] != 0) Log :: fatal(self::_("Fail to list application PHP files.")); @@ -519,7 +528,7 @@ class I18n { ), $php_files[1], // Pass PHP files list via STDIN true, // Escape parameters - App :: root_directory_path() // Run from EesyPHP src directory + $root_directory_path // Run from application root directory ); if (!is_array($result) || $result[0] != 0) Log :: fatal(self::_("Fail to extract messages from PHP files using xgettext.")); @@ -530,12 +539,24 @@ class I18n { foreach(Tpl::static_directories() as $idx => $static_directory) { if (Cli::core_mode() && $static_directory != Tpl::$core_static_directory) continue; if (!Cli::core_mode() && $static_directory == Tpl::$core_static_directory) continue; + // Make path relative to application root directory + $relative_static_directory = App::relative_path($static_directory); + if (!$relative_static_directory) { + Log::debug("Static directory '%s' does not exist, ignore it.", $static_directory); + continue; + } // List JS files to parse + $cmd = array( + 'find', escapeshellarg($relative_static_directory), + '-name', "'*.tpl'", '-type', 'f' + ); + foreach($excluded_paths as $path) + array_push($cmd, "-not", "-path", "'$path'"); $result = run_external_command( - array('find', escapeshellarg(basename($static_directory)), '-name', "'*.js'"), - null, // no STDIN data - false, // do not escape command args (already done) - dirname($static_directory) // Run from parent directory + $cmd, + null, // no STDIN data + false, // do not escape command args (already done) + $root_directory_path // Run from application root directory ); if (!is_array($result) || $result[0] != 0) Log :: fatal( @@ -557,7 +578,7 @@ class I18n { ), $result[1], // Pass JS files list via STDIN true, // Escape arguments - dirname($static_directory) // Run from parent directory + $root_directory_path // Run from application root directory ); if (!is_array($result) || $result[0] != 0) Log :: fatal( @@ -571,15 +592,46 @@ class I18n { foreach (Tpl :: templates_directories() as $idx => $templates_directory) { if (Cli::core_mode() && $templates_directory != Tpl::$core_templates_directory) continue; if (!Cli::core_mode() && $templates_directory == Tpl::$core_templates_directory) continue; + // Make path relative to application root directory + $relative_templates_directory = App::relative_path($templates_directory); + if (!$relative_templates_directory) { + Log::debug("Templates directory '%s' does not exist, ignore it.", $templates_directory); + continue; + } + + // List templates files to parse + $cmd = array( + 'find', escapeshellarg($relative_templates_directory), + '-name', "'*.tpl'", '-type', 'f' + ); + foreach($excluded_paths as $path) + array_push($cmd, "-not", "-path", "'$path'"); + $templates_files = run_external_command( + $cmd, + null, // no STDIN data + false, // do not escape command args (already done) + dirname($templates_directory) // Run from parent directory + ); + if (!is_array($templates_files) || $templates_files[0] != 0) + Log :: fatal( + self::_("Fail to list templates files in directory %s."), + $templates_directory + ); + + // Compute template files file from find command output + $templates_files = explode("\n", $templates_files[1]); + // Extract messages from templates files using tsmarty2c.php + $cmd = array( + PHP_BINARY.' '.App :: root_directory_path(). + "/vendor/smarty-gettext/smarty-gettext/tsmarty2c.php", + ); + array_push($cmd, ...$templates_files); $result = run_external_command( - array( - PHP_BINARY.' '.App :: root_directory_path()."/vendor/smarty-gettext/smarty-gettext/tsmarty2c.php", - basename($templates_directory), - ), - null, // Pass nothing on STDIN - true, // Escape arguments - dirname($templates_directory) // Run from parent directory + $cmd, + null, // Pass nothing on STDIN + true, // Escape arguments + $root_directory_path // Run from application root directory ); if (!is_array($result) || $result[0] != 0) Log :: fatal(