1<?php 2 3// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project 4// 5// All Rights Reserved. See copyright.txt for details and a complete list of authors. 6// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details. 7// $Id$ 8 9namespace Tiki\Command; 10 11use Language_CollectFiles; 12use Language_FileType_Php; 13use Language_FileType_Tpl; 14use Language_GetStrings; 15use Language_WriteFile_Factory; 16use Symfony\Component\Console\Command\Command; 17use Symfony\Component\Console\Helper\ProgressBar; 18use Symfony\Component\Console\Input\InputInterface; 19use Symfony\Component\Console\Output\OutputInterface; 20use Symfony\Component\Console\Input\InputOption; 21use timer; 22 23/** 24 * @package Tiki\Command 25 * 26 * Update lang/xx/language.php files 27 * 28 * Scans a directory (its files) and a set of (individual) files 29 * By default, the directory scanned is the Tiki root, excluding $excludeDirs. By default, the individual files scanned are files in these otherwise excluded directories. 30 * 31 * Examples: 32 * - http://localhost/pathToTiki/get_strings.php -> update all language.php files 33 * - http://localhost/pathToTiki/get_strings.php?lang=fr -> update just lang/fr/language.php file 34 * - http://localhost/pathToTiki/get_strings.php?lang[]=fr&lang[]=pt-br&outputFiles -> update both French 35 * and Brazilian Portuguese language.php files and for each string add a line with 36 * the file where it was found. 37 * 38 * Command line examples: 39 * - php get_strings.php 40 * - php get_strings.php lang=pt-br outputFiles=true 41 * 42 * Only scan lib/, and only part of lib/ (exclude lib/core/Zend and lib/captcha), but still include captchalib.php and index.php 43 * This FAILS as of 2017-09-15, since the language files (for output) are looked for in baseDir. 44 * - php get_strings.php baseDir=lib/ excludeDirs=lib/core/Zend,lib/captcha includeFiles=captchalib.php,index.php fileName=language_r.php 45 * 46 * 47 */ 48 49class GetStringsCommand extends Command 50{ 51 protected function configure(): void 52 { 53 $this 54 ->setName('translation:getstrings') 55 ->setDescription('Update language.php files with new strings') 56 ->setHelp('Scans all Tiki files and adds new English strings to language files. Also reorganizes existing strings.') 57 ->addOption( 58 'lang', 59 'l', 60 InputOption::VALUE_OPTIONAL, 61 'Language code to process eg. lang=pt-br' 62 ) 63 ->addOption( 64 'outputfiles', 65 null, 66 InputOption::VALUE_NONE, 67 'For each string add a line with the file where it was found' 68 ) 69 ->addOption( 70 'exclude', 71 null, 72 InputOption::VALUE_OPTIONAL, 73 'Directories that should be excluded from searching' 74 ) 75 ->addOption( 76 'include', 77 null, 78 InputOption::VALUE_OPTIONAL, 79 'Individual files that should be included in otherwise excluded directories' 80 ) 81 ->addOption( 82 'basedir', 83 null, 84 InputOption::VALUE_OPTIONAL, 85 'The base directory to use. Will invalidate default exclude and include parameters' 86 ) 87 ->addOption( 88 'filename', 89 null, 90 InputOption::VALUE_OPTIONAL, 91 'eg. filename=language_r.php' 92 ); 93 } 94 95 protected function execute(InputInterface $input, OutputInterface $output): void 96 { 97 $timer = new timer(); 98 $timer->start(); 99 100 $options = []; 101 $options['lang'] = $input->getOption('lang') ?: null; 102 $options['outputFiles'] = $input->getOption('outputfiles') ?: null; 103 $excludeDirs = ['dump', 'img', 'lang', 'bin', 'installer/schema', 'vendor_bundled', 'vendor', 'vendor_extra', 'vendor_custom', 'lib/test', 'temp', 'permissioncheck', 'storage', 'tiki_tests', 104 'doc', 'db', 'lib/openlayers', 'tests', 'modules/cache']; 105 $excludeDirs = array_filter($excludeDirs, 'is_dir'); // only keep in the exclude list if the dir exists 106 107 // Files are processed after the base directory, so adding a file here allows to scan it even if its directory was excluded. 108 $includeFiles = ['./lang/langmapping.php', './img/flags/flagnames.php']; 109 110 if ($input->getOption('basedir')) { 111 $options['baseDir'] = $input->getOption('basedir'); 112 113 // when a custom base dir is set, default $includeFiles and $excludeDirs are not used 114 $includeFiles = []; 115 $excludeDirs = []; 116 } 117 if ($input->getOption('exclude')) { 118 $excludeDirs = explode(',', $input->getOption('exclude')); 119 } 120 if ($input->getOption('include')) { 121 $includeFiles = explode(',', $input->getOption('include')); 122 } 123 $options['fileName'] = $input->getOption('filename') ?: null; 124 125 $getStrings = new Language_GetStrings(new Language_CollectFiles, new Language_WriteFile_Factory, $options); 126 127 $getStrings->addFileType(new Language_FileType_Php); 128 $getStrings->addFileType(new Language_FileType_Tpl); 129 130 // skip the following directories 131 $getStrings->collectFiles->setExcludeDirs($excludeDirs); 132 133 // manually add the following files from skipped directories 134 $getStrings->collectFiles->setIncludeFiles($includeFiles); 135 136 $langs = $getStrings->getLanguages(); 137 sort($langs); 138 $output->writeln(count($langs) . ' Languages: ' . implode(' ', $langs)); 139 140 $getStrings->run(); 141 142 $output->writeln('Total time spent: ' . $timer->stop() . ' seconds'); 143 $output->writeln('<comment>You may now review and commit</comment>'); 144 $output->writeln( 145 '<info>Warning: Committing the results of getstrings will prevent identifying broken strings with translation:englishupdate so englishupdate should be run first to prevent gradual translation loss. See englishupdate help for details.</info>' 146 ); 147 } 148} 149