Skip to content

Commit

Permalink
feature: add translationtool command options and check-files action (#…
Browse files Browse the repository at this point in the history
…651)

* feature: add translationtool command options (-h, -v), add check-files action

Signed-off-by: Sebastien Marinier <[email protected]>
Signed-off-by: Sébastien Marinier <[email protected]>
  • Loading branch information
smarinier authored Aug 26, 2024
1 parent 201865f commit 93319dd
Showing 1 changed file with 133 additions and 12 deletions.
145 changes: 133 additions & 12 deletions translations/translationtool/src/translationtool.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ class TranslatableApp {
private $fakeLocaleFile;
private $ignoreFiles;
private $translationsPath;
private $tool;

public function __construct($appPath, $translationsPath) {
public function __construct($appPath, $translationsPath, $tool) {
$this->appPath = $appPath;
$this->translationsPath = $translationsPath;
$this->tool = $tool;

$this->ignoreFiles = [];
$this->fakeAppInfoFile = $this->appPath . '/specialAppInfoFakeDummyForL10nScript.php';
Expand All @@ -59,7 +61,7 @@ public function __construct($appPath, $translationsPath) {
print_r($this->ignoreFiles);
}

public function createPotFile() {
public function createOrCheckPotFile(bool $checkFiles = false) {
$pathToPotFile = $this->translationsPath . '/templates/' . $this->name . '.pot';

// Gather required data
Expand Down Expand Up @@ -95,7 +97,26 @@ public function createPotFile() {
$joinexisting = '--join-existing';
}

exec('xgettext ' . $output . ' ' . $joinexisting . ' ' . $keywords . ' ' . $language . ' ' . escapeshellarg($entry) . ' ' . $additionalArguments);
$extractAll = $tmpfname = $skipErrors = '';
if ($checkFiles) {
$extractAll = '--extract-all';

// modify output
$tmpfname = tempnam(sys_get_temp_dir(), 'checkpot');
$output = '--output=' . $tmpfname;
// extract-all generates a recurrent warning
$skipErrors = "2>/dev/null";
}

$xgetCmd = 'xgettext ' . $output . ' ' . $joinexisting . ' ' . $keywords . ' ' . $language . ' ' . escapeshellarg($entry) . ' ' . $additionalArguments . ' ' . $extractAll . ' ' . $skipErrors;
$this->tool->log($xgetCmd);
exec($xgetCmd);

// checking files
if ($checkFiles) {
$this->checkMissingTranslations($entry, $tmpfname);
unlink($tmpfname);
}
}

// Don't forget to remove the temporary file
Expand All @@ -104,6 +125,34 @@ public function createPotFile() {
$this->deleteFakeFileForLocale();
}

private function checkMissingTranslations(string $entry, string $tmpfname) {
$translations = Gettext\Translations::fromPoFile($tmpfname);
$first=true;
foreach($translations as $translation) {
if (preg_match_all('/(^|[^a-zA-Z_]+)(t\([^\)]*\))/', $translation->getOriginal(), $matches)) {
$suspects = [];
foreach($matches[2] as $miss) {
if (preg_match('/["\']'.$this->name.'["\']/', $miss )) {
$suspects[] = $miss;
}
}
if (empty($suspects)) {
continue;
}
if ($first) {
echo '** Warning: Check potentially missing translations sentences: ' . $this->name . ' ' . $entry . PHP_EOL;
$first = false;
}
if ($translation->hasReferences()) {
echo '> Starting at line ' . $translation->getReferences()[0][1] . PHP_EOL;
}
foreach($suspects as $suspect) {
echo ' -> ' . $suspect . PHP_EOL;
}
}
}
}

public function createNextcloudFiles() {
foreach ($this->findLanguages() as $language) {
$poFile = $this->translationsPath . '/' . $language . '/' . $this->name . '.po';
Expand Down Expand Up @@ -464,6 +513,7 @@ private function deleteFakeFileForLocale() {
class TranslationTool {
private $translationPath;
private $appPaths;
private $verbose = 0;

public function __construct(){
$this->translationPath = getcwd() . '/translationfiles';
Expand All @@ -474,6 +524,10 @@ public function __construct(){
}
}

public function setVerbose(int $verbose) {
$this->verbose = $verbose;
}

public function checkEnvironment() {
// Check if the version of xgettext is at least 0.18.3
$output = [];
Expand All @@ -482,6 +536,8 @@ public function checkEnvironment() {
// we assume the first line looks like this 'xgettext (GNU gettext-tools) 0.19.3'
$version = trim(substr($output[0], 29));

$this->log("xgettext version: ". $version);

if (version_compare($version, '0.18.3', '<')) {
echo 'Minimum expected version of xgettext is 0.18.3. Detected: ' . $version . '".' . PHP_EOL;
return false;
Expand All @@ -503,18 +559,30 @@ public function createPotFiles() {

// iterate over all apps
foreach ($this->appPaths as $appPath) {
$app = new TranslatableApp($appPath, $this->translationPath);
$app->createPotFile();
$this->log('Application path: ' . $appPath);
$app = new TranslatableApp($appPath, $this->translationPath, $this);
$app->createOrCheckPotFile();
}
}

public function convertPoFiles() {
foreach ($this->appPaths as $appPath) {
$app = new TranslatableApp($appPath, $this->translationPath);
$this->log('Application path: ' . $appPath);
$app = new TranslatableApp($appPath, $this->translationPath, $this);
$app->createNextcloudFiles();
}
}

public function checkFiles() {

// iterate over all apps
foreach ($this->appPaths as $appPath) {
$this->log('Application path: ' . $appPath);
$app = new TranslatableApp($appPath, $this->translationPath, $this);
$app->createOrCheckPotFile(true);
}
}

private function findApps($path){
$directoryectoryContent = scandir($path);
foreach ($directoryectoryContent as $entry) {
Expand All @@ -539,7 +607,6 @@ private function findApps($path){
}
}


private function rrmdir($path) {
if (!is_dir($path)) {
return;
Expand All @@ -561,18 +628,70 @@ private function rrmdir($path) {

rmdir($path);
}

public function log(string $message) {
if ($this->verbose == 0) {
return;
}
echo " > " . $message . PHP_EOL;
}
}

// arguments handle
$task = '';
$usage = false;
$verbose = 0;
$returnValue = true;

$index = 0;
foreach ($argv as $arg) {
$index++;
if ($index == 1) {
$TOOLNAME = $arg;
continue;
}
switch($arg) {
case '-h':
case '--help':
$usage = true;
break;
case '-v':
case '--verbose':
$verbose++;
break;
case 'create-pot-files':
case 'convert-po-files':
case 'check-files':
$task = $arg;
break;
default:
echo "Unknown command parameter : " . $arg . PHP_EOL;
$usage = true;
$returnValue = false;
break;
}
}

// read the command line arguments
if(count($argv) < 2) {
if(empty($task) && !$usage) {
echo 'Missing arguments' . PHP_EOL;
echo 'call "' . $argv[0] . ' $task [$appName]' . PHP_EOL;
echo '$task: create-pot-files || convert-po-files' . PHP_EOL;
return false;
$usage = true;
$returnValue = false;
}

if ($usage) {
echo 'Usage:' . PHP_EOL;
echo ' ' . $TOOLNAME . ' <task> [<appName>]' . PHP_EOL;
echo 'Arguments:' . PHP_EOL;
echo ' task: One of: create-pot-files, convert-po-files, check-files' . PHP_EOL;
echo "Options:". PHP_EOL;
echo " -v, --verbose Verbose mode". PHP_EOL;
echo " -h, --help Display command usage". PHP_EOL;
return $returnValue;
}
$task = $argv[1];

$tool = new TranslationTool();
$tool->setVerbose($verbose);
if (!$tool->checkEnvironment()) {
return false;
}
Expand All @@ -581,6 +700,8 @@ private function rrmdir($path) {
$tool->createPotFiles();
} elseif ($task === 'convert-po-files') {
$tool->convertPoFiles();
} elseif ($task === 'check-files') {
$tool->checkFiles();
} else {
echo 'Unknown task: "' . $task . '".' . PHP_EOL;
return false;
Expand Down

0 comments on commit 93319dd

Please sign in to comment.