├── index.php ├── composer.json ├── LICENSE ├── CHANGES.md ├── README.md ├── src └── Language_Pack_Maker.php └── composer.lock /index.php: -------------------------------------------------------------------------------- 1 | \n"; 17 | echo ">>Generating Language Pack Zip Files and JSON file<<\n\n"; 18 | ( new Fragen\Language_Pack_Maker\Language_Pack_Maker() )->run(); 19 | echo "\n"; 20 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "afragen/language-pack-maker", 3 | "description": "Library that helps create git sourced WordPress Language Packs from po files.", 4 | "version": "3.2.1", 5 | "type": "library", 6 | "license": "MIT", 7 | "keywords": [ 8 | "wordpress", 9 | "language packs", 10 | "translations" 11 | ], 12 | "authors": [ 13 | { 14 | "name": "Andy Fragen", 15 | "email": "andy@thefragens.com", 16 | "homepage": "https://thefragens.com", 17 | "role": "Developer" 18 | } 19 | ], 20 | "support": { 21 | "issues": "https://github.com/afragen/language-pack-maker/issues", 22 | "source": "https://github.com/afragen/language-pack-maker" 23 | }, 24 | "prefer-stable": true, 25 | "require": { 26 | "php": ">=7.0", 27 | "gettext/gettext": "^4.8", 28 | "wp-cli/i18n-command": "^2", 29 | "afragen/wp-cli-runner": "^0.1" 30 | }, 31 | "autoload": { 32 | "psr-4": { 33 | "Fragen\\Language_Pack_Maker\\": "src/" 34 | }, 35 | "files": [ 36 | "index.php" 37 | ] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Andy Fragen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | ## [unreleased] 2 | 3 | ## 3.2.1 / 2024-11-11 4 | * mess with `create_js_files()` 5 | * update README 6 | 7 | ## 3.2.0 / 2024-11-09 8 | * use new `class MakePhpCommand` to create .i18n.php files 9 | 10 | ## 3.1.1 / 2022-01-19 11 | * need to add required third parameter to `make_json()` 12 | 13 | ## 3.1.0 / 2020-06-04 14 | * use new `class MakeMoCommand` in `wp-cli/i18n-command@v2.2.3` to create .mo files 15 | 16 | ## 3.0.0 / 2019-12-10 17 | * process .json files in the framework 18 | * added WP-CLI _loader_ as composer module, [fork of polevaultweb/phpunit-wp-cli-runner](https://github.com/polevaultweb/phpunit-wp-cli-runner) 19 | * cleanup temp directory afterwards 20 | 21 | ## 2.0.0 / 2019-11-26 22 | * fix processing of .json files, thanks @ahmader 23 | * use gettext/gettext to parse translation headers for 'PO-Revision-Date' 24 | * create the .mo files from the .po files with gettext/gettext 25 | 26 | ## 1.8.0 / 2019-11-24 27 | * put version info in composer.json 28 | * add .json files to processing for `wp_set_script_translations` 29 | 30 | ## 1.6.0 / 2018-09-11 31 | * moved action from constructor 32 | * update README 33 | * update composer.json 34 | 35 | ## 1.5.0 / 2017-12-09 36 | * renamed on GitHub 37 | 38 | ## 1.4.0 / 2017-07-02 39 | * changed namespace to `Fragen\Language_Pack_Maker` 40 | * minor linting improvements 41 | 42 | ## 1.3.0 / 2016-09-24 43 | * get updated date from .po file header 44 | 45 | ## 1.2.0 / 2016-09-19 46 | * use single `glob()` in `list_directory()` 47 | 48 | ## 1.1.0 / 2016-09-18 49 | * use `glob()` in `list_directory()` 50 | 51 | ## 1.0.0 / 2016-09-12 52 | * initial commit 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Language Pack Maker 2 | 3 | Requires PHP 7.0 or higher. 4 | 5 | Uses `class Language_Pack_Maker` installed via composer into your local translation repository to create a directory of zip archives of translation .mo/.po/.json files and a `language-pack.json` file containing data to pass to [Git Updater](https://github.com/afragen/git-updater) or [Translations Updater library](https://github.com/afragen/translations-updater). 6 | 7 | Install the package via composer. 8 | 9 | Run the composer command: ```composer require afragen/language-pack-maker:dev-master``` 10 | 11 | ## Requirements 12 | 13 | This library requires all .po files to be in a `/languages` directory located in the repository root. 14 | 15 | * It will copy all .po files from `/languages` to a temporary directory. 16 | * It will create .mo files from the .po files. 17 | * It will create .l10n.php files from the .po files. 18 | * It will create .json translation files for your javascript. 19 | * It will create zipfiles in a `/packages` directory in the repository root. 20 | * It will create a `language-pack.json` file in the repository root. 21 | * It will cleanup/remove the temporary directory when finished. 22 | 23 | The format of the generated JSON file is as follows. 24 | 25 | ```json 26 | [ 27 | { 28 | "{language}": [ 29 | { 30 | "type": "{plugin|theme} from GitHub Updater", 31 | "slug": "{$slug}", 32 | "language": "en_US", 33 | "version": "from GitHub Updater", 34 | "updated": "PO-Revision-Date from .po file header", 35 | "package": "/packages/github-updater-en_US.zip", 36 | "autoupdate": "1" 37 | } 38 | ] 39 | } 40 | ] 41 | ``` 42 | 43 | The update transient expects the `$transient->translations` in the following format. 44 | 45 | ```php 46 | $transient->translations( array( 47 | 0 => array( 48 | 'type' => 'plugin', 49 | 'slug' => 'akismet', 50 | 'language' => 'de_CH', 51 | 'version' => '3.1.11', 52 | 'updated' => '2016-05-12 18:04:38', 53 | 'package' => 'https://downloads.wordpress.org/translation/plugin/akismet/3.1.11/de_CH.zip', 54 | 'autoupdate' => 1, 55 | 56 | ), 57 | ) ); 58 | ``` 59 | 60 | [Git Updater](https://github.com/afragen/git-updater) or the [Translations Updater library](https://github.com/afragen/translations-updater) will merge the correlative plugin or theme data with the data retrieved from the `language-pack.json` to add data to the update transient. Language updates will appear in the WordPress dashboard. 61 | 62 | To utilize the Language Pack Creator, you will need to open and run `http://localhost//vendor/autoload.php` in localhost. This will create the necessary .mo, .l10n.php, .json, zipfiles, and `language-pack.json`. 63 | 64 | With the following added to your `composer.json` file, it will run the sequence described above on `composer make-language-packs`. 65 | 66 | ``` 67 | "scripts": { 68 | "make-language-packs": [ 69 | "php ./vendor/autoload.php" 70 | ] 71 | } 72 | ``` 73 | -------------------------------------------------------------------------------- /src/Language_Pack_Maker.php: -------------------------------------------------------------------------------- 1 | root_dir = dirname( __DIR__, 4 ); 80 | $this->language_files_dir = $this->root_dir . '/languages'; 81 | $this->temp_language_files_dir = $this->root_dir . '/tmp'; 82 | $this->packages_dir = $this->root_dir . '/packages'; 83 | @mkdir( $this->language_files_dir, 0777 ); 84 | @mkdir( $this->temp_language_files_dir, 0777 ); 85 | @mkdir( $this->packages_dir, 0777 ); 86 | } 87 | 88 | /** 89 | * Start making stuff. 90 | */ 91 | public function run() { 92 | $this->directory_list = $this->list_directory( $this->language_files_dir ); 93 | $this->copy_to_dir( $this->temp_language_files_dir ); 94 | $this->translations = $this->process_directory( $this->directory_list ); 95 | 96 | Runner::init( $this->root_dir . '/vendor' ); 97 | $this->create_mo_files( $this->temp_language_files_dir ); 98 | $this->create_php_files( $this->temp_language_files_dir ); 99 | $this->create_js_files( $this->temp_language_files_dir ); 100 | 101 | $this->packages = $this->create_packages( $this->temp_language_files_dir ); 102 | $this->create_language_packs(); 103 | $this->create_json(); 104 | $this->clean_up_dir( $this->temp_language_files_dir, $this->directory_list ); 105 | } 106 | 107 | /** 108 | * Create an array of the directory contents. 109 | * 110 | * @param string $dir filepath. 111 | * 112 | * @return array $dir_list Listing of directory contents. 113 | */ 114 | private function list_directory( $dir ) { 115 | $dir_list = []; 116 | 117 | // Only add mo/po/zip/json/l10n.php files. 118 | foreach ( glob( $dir . '/*.{mo,po,zip,json,l10n.php}', GLOB_BRACE ) as $file ) { 119 | $dir_list[] = basename( $file ); 120 | } 121 | 122 | return $dir_list; 123 | } 124 | 125 | /** 126 | * Copy files from one directory to another directory. 127 | * 128 | * @param string $dir File path to directory. 129 | * 130 | * @return void 131 | */ 132 | private function copy_to_dir( $dir ) { 133 | foreach ( $this->directory_list as $file ) { 134 | copy( "$this->language_files_dir/$file", "$dir/$file" ); 135 | } 136 | $this->directory_list = $this->list_directory( $dir ); 137 | } 138 | 139 | /** 140 | * Returns a string of the translation name. 141 | * 142 | * @param string $filename Filename. 143 | * 144 | * @return string $dir_list Listing of directory contents. 145 | */ 146 | private function process_name( $filename ) { 147 | if ( 'json' === pathinfo( $filename, PATHINFO_EXTENSION ) ) { 148 | // Parse filename. 149 | $list = explode( '-', pathinfo( $filename, PATHINFO_FILENAME ) ); 150 | 151 | // Remove the md5 part. 152 | array_pop( $list ); 153 | 154 | return implode( '-', $list ); 155 | } 156 | 157 | return pathinfo( $filename, PATHINFO_FILENAME ); 158 | } 159 | 160 | /** 161 | * Returns an array of translations with stripped file extension. 162 | * 163 | * @param array $dir_list Listing of directory contents. 164 | * 165 | * @return array $translation_list An array of translations. 166 | */ 167 | private function process_directory( $dir_list ) { 168 | $translation_list = array_map( 169 | [ $this, 'process_name' ], 170 | $dir_list 171 | ); 172 | $translation_list = array_unique( $translation_list ); 173 | 174 | return $translation_list; 175 | } 176 | 177 | /** 178 | * Create .mo files from .po files. 179 | * 180 | * @param string $dir File path to temporary language files directory. 181 | * 182 | * @return void 183 | */ 184 | private function create_mo_files( $dir ) { 185 | $class = new MakeMoCommand(); 186 | $reflection = new \ReflectionClass( '\WP_CLI\I18n\MakeMoCommand' ); 187 | $invoke = $reflection->getMethod( '__invoke' ); 188 | $invoke->invokeArgs( $class, [ [ $dir ], [] ] ); 189 | print( " (.mo)\n"); 190 | } 191 | 192 | /** 193 | * Create .l10n.php files from .po files. 194 | * 195 | * @param string $dir File path to temporary language files directory. 196 | * 197 | * @return void 198 | */ 199 | private function create_php_files( $dir ) { 200 | $class = new MakePhpCommand(); 201 | $reflection = new \ReflectionClass( '\WP_CLI\I18n\MakePhpCommand' ); 202 | $invoke = $reflection->getMethod( '__invoke' ); 203 | $invoke->invokeArgs( $class, [ [ $dir ], [] ] ); 204 | print( " (.l10n.php)\n"); 205 | } 206 | 207 | /** 208 | * Create .json JS translation files from .po file. 209 | * 210 | * @param string $dir File path to temporary language files directory. 211 | * 212 | * @return void 213 | */ 214 | private function create_js_files( $dir ) { 215 | $assoc_args = [ 216 | 'purge' => false, 217 | 'pretty-print' => false, 218 | ]; 219 | 220 | $class = new MakeJsonCommand(); 221 | $reflection = new \ReflectionClass( '\WP_CLI\I18n\MakeJsonCommand' ); 222 | $invoke = $reflection->getMethod( '__invoke' ); 223 | $invoke->setAccessible( true ); 224 | /* $make_json = $reflection->getMethod( 'make_json' ); 225 | 226 | foreach ( glob( "$dir/*.po" ) as $file ) { 227 | $base = str_replace( '.po', '', basename( $file ) ); 228 | $po_list[ $base ] = $file; 229 | } 230 | 231 | foreach ( $this->translations as $locale ) { 232 | $params = [ "$dir/$locale.po", $dir, null ]; 233 | $make_json->invokeArgs( $class, $params ); 234 | } */ 235 | $invoke->invokeArgs( $class, [ [ $dir ], $assoc_args ] ); 236 | print( " (.json)\n"); 237 | } 238 | 239 | /** 240 | * Creates an associative array of translations from directory listing. 241 | * 242 | * @param string $dir File path to directory. 243 | * 244 | * @return array $packages Associative array of translation files per translation. 245 | */ 246 | private function create_packages( $dir ) { 247 | $packages = []; 248 | $this->directory_list = $this->list_directory( $dir ); 249 | foreach ( $this->translations as $translation ) { 250 | $package = []; 251 | foreach ( $this->directory_list as $file ) { 252 | if ( false !== stripos( $file, $translation ) ) { 253 | $package[] = "$dir/$file"; 254 | } 255 | } 256 | $packages[ $translation ] = $package; 257 | } 258 | 259 | return $packages; 260 | } 261 | 262 | /** 263 | * Create language pack zipfiles. 264 | */ 265 | private function create_language_packs() { 266 | foreach ( $this->packages as $translation => $files ) { 267 | $this->create_zip( $files, $this->packages_dir . '/' . $translation . '.zip', true ); 268 | } 269 | } 270 | 271 | /** 272 | * Create individual zipfile. 273 | * 274 | * @link https://davidwalsh.name/create-zip-php 275 | * 276 | * @param array $files Array of files for each language pack. 277 | * @param string $destination Filepath to zipfile. 278 | * @param bool $overwrite Boolean to set zipfile creation overwrite mode. 279 | * 280 | * @return bool 281 | */ 282 | private function create_zip( $files = [], $destination = '', $overwrite = true ) { 283 | // if the zip file already exists and overwrite is false, return false. 284 | if ( file_exists( $destination ) && ! $overwrite ) { 285 | return false; 286 | } 287 | 288 | // create the archive. 289 | $zip = new \ZipArchive(); 290 | if ( true !== $zip->open( $destination, \ZIPARCHIVE::OVERWRITE | \ZIPARCHIVE::CREATE ) ) { 291 | return false; 292 | } 293 | // add the files. 294 | foreach ( $files as $file ) { 295 | $zip->addFile( $file, basename( $file ) ); 296 | } 297 | 298 | // close the zip -- done! 299 | $zip->close(); 300 | 301 | // check to make sure the file exists. 302 | if ( file_exists( $destination ) ) { 303 | printf( "\n" . basename( $destination ) . ' created.' ); 304 | } else { 305 | printf( "\n>> " . basename( $destination ) . ' failed. <<' ); 306 | } 307 | } 308 | 309 | /** 310 | * Create JSON file of translations for export and use by GitHub Updater. 311 | */ 312 | private function create_json() { 313 | $packages = $this->list_directory( $this->packages_dir ); 314 | $arr = []; 315 | 316 | foreach ( $packages as $package ) { 317 | foreach ( $this->translations as $translation ) { 318 | if ( false !== stripos( $package, $translation ) ) { 319 | $locale = ltrim( strrchr( $translation, '-' ), '-' ); 320 | $arr[ $locale ]['slug'] = stristr( $translation, strrchr( $translation, '-' ), true ); 321 | $arr[ $locale ]['language'] = $locale; 322 | $arr[ $locale ]['updated'] = $this->get_po_revision( "$translation.po" ); 323 | $arr[ $locale ]['package'] = '/packages/' . $package; 324 | $arr[ $locale ]['autoupdate'] = '1'; 325 | } 326 | } 327 | } 328 | 329 | file_put_contents( $this->root_dir . '/language-pack.json', json_encode( $arr ) ); 330 | printf( "\n\n" . 'language-pack.json created.' . "\n" ); 331 | } 332 | 333 | /** 334 | * Returns PO-Revision-Date from .po file. 335 | * 336 | * @param $file File name. 337 | * 338 | * @return string 339 | */ 340 | private function get_po_revision( $file ) { 341 | $file = $this->temp_language_files_dir . '/' . $file; 342 | $translations = Translations::fromPoFile( $file ); 343 | 344 | return $translations->getHeader( 'PO-Revision-Date' ); 345 | } 346 | 347 | /** 348 | * Cleanup directory. 349 | * 350 | * @param string $dir Path to directory. 351 | * @param array $filelist Array of files. 352 | * 353 | * @return void 354 | */ 355 | private function clean_up_dir( $dir, $filelist ) { 356 | foreach ( $filelist as $file ) { 357 | @unlink( "$dir/$file" ); 358 | } 359 | @rmdir( $dir ); 360 | } 361 | } 362 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "b86e43221f9232579cd6aea0169e6109", 8 | "packages": [ 9 | { 10 | "name": "afragen/wp-cli-runner", 11 | "version": "0.1.2", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/afragen/wp-cli-runner.git", 15 | "reference": "87ee6ef715d36f6d7983ce49d03d12ffdcbe46a9" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/afragen/wp-cli-runner/zipball/87ee6ef715d36f6d7983ce49d03d12ffdcbe46a9", 20 | "reference": "87ee6ef715d36f6d7983ce49d03d12ffdcbe46a9", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "wp-cli/wp-cli": "^2" 25 | }, 26 | "type": "library", 27 | "autoload": { 28 | "psr-4": { 29 | "Fragen\\WP_CLI_Runner\\": "src" 30 | } 31 | }, 32 | "notification-url": "https://packagist.org/downloads/", 33 | "license": [ 34 | "GPL-2.0-or-later" 35 | ], 36 | "description": "Helper to test custom WP-CLI commands by bootstrapping WP-CLI", 37 | "homepage": "https://github.com/afragen/wp-cli-runner", 38 | "keywords": [ 39 | "testing", 40 | "wp-cli" 41 | ], 42 | "support": { 43 | "source": "https://github.com/afragen/wp-cli-runner/tree/0.1.2" 44 | }, 45 | "time": "2021-05-21T15:31:14+00:00" 46 | }, 47 | { 48 | "name": "eftec/bladeone", 49 | "version": "3.52", 50 | "source": { 51 | "type": "git", 52 | "url": "https://github.com/EFTEC/BladeOne.git", 53 | "reference": "a19bf66917de0b29836983db87a455a4f6e32148" 54 | }, 55 | "dist": { 56 | "type": "zip", 57 | "url": "https://api.github.com/repos/EFTEC/BladeOne/zipball/a19bf66917de0b29836983db87a455a4f6e32148", 58 | "reference": "a19bf66917de0b29836983db87a455a4f6e32148", 59 | "shasum": "" 60 | }, 61 | "require": { 62 | "ext-json": "*", 63 | "php": ">=5.6" 64 | }, 65 | "require-dev": { 66 | "friendsofphp/php-cs-fixer": "^2.16.1", 67 | "phpunit/phpunit": "^5.7", 68 | "squizlabs/php_codesniffer": "^3.5.4" 69 | }, 70 | "suggest": { 71 | "eftec/bladeonehtml": "Extension to create forms", 72 | "ext-mbstring": "This extension is used if it's active" 73 | }, 74 | "type": "library", 75 | "autoload": { 76 | "psr-4": { 77 | "eftec\\bladeone\\": "lib/" 78 | } 79 | }, 80 | "notification-url": "https://packagist.org/downloads/", 81 | "license": [ 82 | "MIT" 83 | ], 84 | "authors": [ 85 | { 86 | "name": "Jorge Patricio Castro Castillo", 87 | "email": "jcastro@eftec.cl" 88 | } 89 | ], 90 | "description": "The standalone version Blade Template Engine from Laravel in a single php file", 91 | "homepage": "https://github.com/EFTEC/BladeOne", 92 | "keywords": [ 93 | "blade", 94 | "php", 95 | "template", 96 | "templating", 97 | "view" 98 | ], 99 | "support": { 100 | "issues": "https://github.com/EFTEC/BladeOne/issues", 101 | "source": "https://github.com/EFTEC/BladeOne/tree/3.52" 102 | }, 103 | "time": "2021-04-17T13:49:01+00:00" 104 | }, 105 | { 106 | "name": "gettext/gettext", 107 | "version": "v4.8.12", 108 | "source": { 109 | "type": "git", 110 | "url": "https://github.com/php-gettext/Gettext.git", 111 | "reference": "11af89ee6c087db3cf09ce2111a150bca5c46e12" 112 | }, 113 | "dist": { 114 | "type": "zip", 115 | "url": "https://api.github.com/repos/php-gettext/Gettext/zipball/11af89ee6c087db3cf09ce2111a150bca5c46e12", 116 | "reference": "11af89ee6c087db3cf09ce2111a150bca5c46e12", 117 | "shasum": "" 118 | }, 119 | "require": { 120 | "gettext/languages": "^2.3", 121 | "php": ">=5.4.0" 122 | }, 123 | "require-dev": { 124 | "illuminate/view": "^5.0.x-dev", 125 | "phpunit/phpunit": "^4.8|^5.7|^6.5", 126 | "squizlabs/php_codesniffer": "^3.0", 127 | "symfony/yaml": "~2", 128 | "twig/extensions": "*", 129 | "twig/twig": "^1.31|^2.0" 130 | }, 131 | "suggest": { 132 | "illuminate/view": "Is necessary if you want to use the Blade extractor", 133 | "symfony/yaml": "Is necessary if you want to use the Yaml extractor/generator", 134 | "twig/extensions": "Is necessary if you want to use the Twig extractor", 135 | "twig/twig": "Is necessary if you want to use the Twig extractor" 136 | }, 137 | "type": "library", 138 | "autoload": { 139 | "psr-4": { 140 | "Gettext\\": "src" 141 | } 142 | }, 143 | "notification-url": "https://packagist.org/downloads/", 144 | "license": [ 145 | "MIT" 146 | ], 147 | "authors": [ 148 | { 149 | "name": "Oscar Otero", 150 | "email": "oom@oscarotero.com", 151 | "homepage": "http://oscarotero.com", 152 | "role": "Developer" 153 | } 154 | ], 155 | "description": "PHP gettext manager", 156 | "homepage": "https://github.com/oscarotero/Gettext", 157 | "keywords": [ 158 | "JS", 159 | "gettext", 160 | "i18n", 161 | "mo", 162 | "po", 163 | "translation" 164 | ], 165 | "support": { 166 | "email": "oom@oscarotero.com", 167 | "issues": "https://github.com/oscarotero/Gettext/issues", 168 | "source": "https://github.com/php-gettext/Gettext/tree/v4.8.12" 169 | }, 170 | "funding": [ 171 | { 172 | "url": "https://paypal.me/oscarotero", 173 | "type": "custom" 174 | }, 175 | { 176 | "url": "https://github.com/oscarotero", 177 | "type": "github" 178 | }, 179 | { 180 | "url": "https://www.patreon.com/misteroom", 181 | "type": "patreon" 182 | } 183 | ], 184 | "time": "2024-05-18T10:25:07+00:00" 185 | }, 186 | { 187 | "name": "gettext/languages", 188 | "version": "2.10.0", 189 | "source": { 190 | "type": "git", 191 | "url": "https://github.com/php-gettext/Languages.git", 192 | "reference": "4d61d67fe83a2ad85959fe6133d6d9ba7dddd1ab" 193 | }, 194 | "dist": { 195 | "type": "zip", 196 | "url": "https://api.github.com/repos/php-gettext/Languages/zipball/4d61d67fe83a2ad85959fe6133d6d9ba7dddd1ab", 197 | "reference": "4d61d67fe83a2ad85959fe6133d6d9ba7dddd1ab", 198 | "shasum": "" 199 | }, 200 | "require": { 201 | "php": ">=5.3" 202 | }, 203 | "require-dev": { 204 | "phpunit/phpunit": "^4.8 || ^5.7 || ^6.5 || ^7.5 || ^8.4" 205 | }, 206 | "bin": [ 207 | "bin/export-plural-rules" 208 | ], 209 | "type": "library", 210 | "autoload": { 211 | "psr-4": { 212 | "Gettext\\Languages\\": "src/" 213 | } 214 | }, 215 | "notification-url": "https://packagist.org/downloads/", 216 | "license": [ 217 | "MIT" 218 | ], 219 | "authors": [ 220 | { 221 | "name": "Michele Locati", 222 | "email": "mlocati@gmail.com", 223 | "role": "Developer" 224 | } 225 | ], 226 | "description": "gettext languages with plural rules", 227 | "homepage": "https://github.com/php-gettext/Languages", 228 | "keywords": [ 229 | "cldr", 230 | "i18n", 231 | "internationalization", 232 | "l10n", 233 | "language", 234 | "languages", 235 | "localization", 236 | "php", 237 | "plural", 238 | "plural rules", 239 | "plurals", 240 | "translate", 241 | "translations", 242 | "unicode" 243 | ], 244 | "support": { 245 | "issues": "https://github.com/php-gettext/Languages/issues", 246 | "source": "https://github.com/php-gettext/Languages/tree/2.10.0" 247 | }, 248 | "funding": [ 249 | { 250 | "url": "https://paypal.me/mlocati", 251 | "type": "custom" 252 | }, 253 | { 254 | "url": "https://github.com/mlocati", 255 | "type": "github" 256 | } 257 | ], 258 | "time": "2022-10-18T15:00:10+00:00" 259 | }, 260 | { 261 | "name": "mck89/peast", 262 | "version": "v1.16.3", 263 | "source": { 264 | "type": "git", 265 | "url": "https://github.com/mck89/peast.git", 266 | "reference": "645ec21b650bc2aced18285c85f220d22afc1430" 267 | }, 268 | "dist": { 269 | "type": "zip", 270 | "url": "https://api.github.com/repos/mck89/peast/zipball/645ec21b650bc2aced18285c85f220d22afc1430", 271 | "reference": "645ec21b650bc2aced18285c85f220d22afc1430", 272 | "shasum": "" 273 | }, 274 | "require": { 275 | "ext-mbstring": "*", 276 | "php": ">=5.4.0" 277 | }, 278 | "require-dev": { 279 | "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0" 280 | }, 281 | "type": "library", 282 | "extra": { 283 | "branch-alias": { 284 | "dev-master": "1.16.3-dev" 285 | } 286 | }, 287 | "autoload": { 288 | "psr-4": { 289 | "Peast\\": "lib/Peast/" 290 | } 291 | }, 292 | "notification-url": "https://packagist.org/downloads/", 293 | "license": [ 294 | "BSD-3-Clause" 295 | ], 296 | "authors": [ 297 | { 298 | "name": "Marco Marchiò", 299 | "email": "marco.mm89@gmail.com" 300 | } 301 | ], 302 | "description": "Peast is PHP library that generates AST for JavaScript code", 303 | "support": { 304 | "issues": "https://github.com/mck89/peast/issues", 305 | "source": "https://github.com/mck89/peast/tree/v1.16.3" 306 | }, 307 | "time": "2024-07-23T14:00:32+00:00" 308 | }, 309 | { 310 | "name": "mustache/mustache", 311 | "version": "v2.14.2", 312 | "source": { 313 | "type": "git", 314 | "url": "https://github.com/bobthecow/mustache.php.git", 315 | "reference": "e62b7c3849d22ec55f3ec425507bf7968193a6cb" 316 | }, 317 | "dist": { 318 | "type": "zip", 319 | "url": "https://api.github.com/repos/bobthecow/mustache.php/zipball/e62b7c3849d22ec55f3ec425507bf7968193a6cb", 320 | "reference": "e62b7c3849d22ec55f3ec425507bf7968193a6cb", 321 | "shasum": "" 322 | }, 323 | "require": { 324 | "php": ">=5.2.4" 325 | }, 326 | "require-dev": { 327 | "friendsofphp/php-cs-fixer": "~1.11", 328 | "phpunit/phpunit": "~3.7|~4.0|~5.0" 329 | }, 330 | "type": "library", 331 | "autoload": { 332 | "psr-0": { 333 | "Mustache": "src/" 334 | } 335 | }, 336 | "notification-url": "https://packagist.org/downloads/", 337 | "license": [ 338 | "MIT" 339 | ], 340 | "authors": [ 341 | { 342 | "name": "Justin Hileman", 343 | "email": "justin@justinhileman.info", 344 | "homepage": "http://justinhileman.com" 345 | } 346 | ], 347 | "description": "A Mustache implementation in PHP.", 348 | "homepage": "https://github.com/bobthecow/mustache.php", 349 | "keywords": [ 350 | "mustache", 351 | "templating" 352 | ], 353 | "support": { 354 | "issues": "https://github.com/bobthecow/mustache.php/issues", 355 | "source": "https://github.com/bobthecow/mustache.php/tree/v2.14.2" 356 | }, 357 | "time": "2022-08-23T13:07:01+00:00" 358 | }, 359 | { 360 | "name": "symfony/finder", 361 | "version": "v7.1.6", 362 | "source": { 363 | "type": "git", 364 | "url": "https://github.com/symfony/finder.git", 365 | "reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8" 366 | }, 367 | "dist": { 368 | "type": "zip", 369 | "url": "https://api.github.com/repos/symfony/finder/zipball/2cb89664897be33f78c65d3d2845954c8d7a43b8", 370 | "reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8", 371 | "shasum": "" 372 | }, 373 | "require": { 374 | "php": ">=8.2" 375 | }, 376 | "require-dev": { 377 | "symfony/filesystem": "^6.4|^7.0" 378 | }, 379 | "type": "library", 380 | "autoload": { 381 | "psr-4": { 382 | "Symfony\\Component\\Finder\\": "" 383 | }, 384 | "exclude-from-classmap": [ 385 | "/Tests/" 386 | ] 387 | }, 388 | "notification-url": "https://packagist.org/downloads/", 389 | "license": [ 390 | "MIT" 391 | ], 392 | "authors": [ 393 | { 394 | "name": "Fabien Potencier", 395 | "email": "fabien@symfony.com" 396 | }, 397 | { 398 | "name": "Symfony Community", 399 | "homepage": "https://symfony.com/contributors" 400 | } 401 | ], 402 | "description": "Finds files and directories via an intuitive fluent interface", 403 | "homepage": "https://symfony.com", 404 | "support": { 405 | "source": "https://github.com/symfony/finder/tree/v7.1.6" 406 | }, 407 | "funding": [ 408 | { 409 | "url": "https://symfony.com/sponsor", 410 | "type": "custom" 411 | }, 412 | { 413 | "url": "https://github.com/fabpot", 414 | "type": "github" 415 | }, 416 | { 417 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 418 | "type": "tidelift" 419 | } 420 | ], 421 | "time": "2024-10-01T08:31:23+00:00" 422 | }, 423 | { 424 | "name": "wp-cli/i18n-command", 425 | "version": "v2.6.3", 426 | "source": { 427 | "type": "git", 428 | "url": "https://github.com/wp-cli/i18n-command.git", 429 | "reference": "065bb3758fcbff922f1b7a01ab702aab0da79803" 430 | }, 431 | "dist": { 432 | "type": "zip", 433 | "url": "https://api.github.com/repos/wp-cli/i18n-command/zipball/065bb3758fcbff922f1b7a01ab702aab0da79803", 434 | "reference": "065bb3758fcbff922f1b7a01ab702aab0da79803", 435 | "shasum": "" 436 | }, 437 | "require": { 438 | "eftec/bladeone": "3.52", 439 | "gettext/gettext": "^4.8", 440 | "mck89/peast": "^1.13.11", 441 | "wp-cli/wp-cli": "^2.5" 442 | }, 443 | "require-dev": { 444 | "wp-cli/scaffold-command": "^1.2 || ^2", 445 | "wp-cli/wp-cli-tests": "^4" 446 | }, 447 | "suggest": { 448 | "ext-json": "Used for reading and generating JSON translation files", 449 | "ext-mbstring": "Used for calculating include/exclude matches in code extraction" 450 | }, 451 | "type": "wp-cli-package", 452 | "extra": { 453 | "branch-alias": { 454 | "dev-main": "2.x-dev" 455 | }, 456 | "bundled": true, 457 | "commands": [ 458 | "i18n", 459 | "i18n make-pot", 460 | "i18n make-json", 461 | "i18n make-mo", 462 | "i18n make-php", 463 | "i18n update-po" 464 | ] 465 | }, 466 | "autoload": { 467 | "files": [ 468 | "i18n-command.php" 469 | ], 470 | "psr-4": { 471 | "WP_CLI\\I18n\\": "src/" 472 | } 473 | }, 474 | "notification-url": "https://packagist.org/downloads/", 475 | "license": [ 476 | "MIT" 477 | ], 478 | "authors": [ 479 | { 480 | "name": "Pascal Birchler", 481 | "homepage": "https://pascalbirchler.com/" 482 | } 483 | ], 484 | "description": "Provides internationalization tools for WordPress projects.", 485 | "homepage": "https://github.com/wp-cli/i18n-command", 486 | "support": { 487 | "issues": "https://github.com/wp-cli/i18n-command/issues", 488 | "source": "https://github.com/wp-cli/i18n-command/tree/v2.6.3" 489 | }, 490 | "time": "2024-10-01T11:16:25+00:00" 491 | }, 492 | { 493 | "name": "wp-cli/mustangostang-spyc", 494 | "version": "0.6.3", 495 | "source": { 496 | "type": "git", 497 | "url": "https://github.com/wp-cli/spyc.git", 498 | "reference": "6aa0b4da69ce9e9a2c8402dab8d43cf32c581cc7" 499 | }, 500 | "dist": { 501 | "type": "zip", 502 | "url": "https://api.github.com/repos/wp-cli/spyc/zipball/6aa0b4da69ce9e9a2c8402dab8d43cf32c581cc7", 503 | "reference": "6aa0b4da69ce9e9a2c8402dab8d43cf32c581cc7", 504 | "shasum": "" 505 | }, 506 | "require": { 507 | "php": ">=5.3.1" 508 | }, 509 | "require-dev": { 510 | "phpunit/phpunit": "4.3.*@dev" 511 | }, 512 | "type": "library", 513 | "extra": { 514 | "branch-alias": { 515 | "dev-master": "0.5.x-dev" 516 | } 517 | }, 518 | "autoload": { 519 | "files": [ 520 | "includes/functions.php" 521 | ], 522 | "psr-4": { 523 | "Mustangostang\\": "src/" 524 | } 525 | }, 526 | "notification-url": "https://packagist.org/downloads/", 527 | "license": [ 528 | "MIT" 529 | ], 530 | "authors": [ 531 | { 532 | "name": "mustangostang", 533 | "email": "vlad.andersen@gmail.com" 534 | } 535 | ], 536 | "description": "A simple YAML loader/dumper class for PHP (WP-CLI fork)", 537 | "homepage": "https://github.com/mustangostang/spyc/", 538 | "support": { 539 | "source": "https://github.com/wp-cli/spyc/tree/autoload" 540 | }, 541 | "time": "2017-04-25T11:26:20+00:00" 542 | }, 543 | { 544 | "name": "wp-cli/php-cli-tools", 545 | "version": "v0.11.22", 546 | "source": { 547 | "type": "git", 548 | "url": "https://github.com/wp-cli/php-cli-tools.git", 549 | "reference": "a6bb94664ca36d0962f9c2ff25591c315a550c51" 550 | }, 551 | "dist": { 552 | "type": "zip", 553 | "url": "https://api.github.com/repos/wp-cli/php-cli-tools/zipball/a6bb94664ca36d0962f9c2ff25591c315a550c51", 554 | "reference": "a6bb94664ca36d0962f9c2ff25591c315a550c51", 555 | "shasum": "" 556 | }, 557 | "require": { 558 | "php": ">= 5.3.0" 559 | }, 560 | "require-dev": { 561 | "roave/security-advisories": "dev-latest", 562 | "wp-cli/wp-cli-tests": "^4" 563 | }, 564 | "type": "library", 565 | "extra": { 566 | "branch-alias": { 567 | "dev-master": "0.11.x-dev" 568 | } 569 | }, 570 | "autoload": { 571 | "files": [ 572 | "lib/cli/cli.php" 573 | ], 574 | "psr-0": { 575 | "cli": "lib/" 576 | } 577 | }, 578 | "notification-url": "https://packagist.org/downloads/", 579 | "license": [ 580 | "MIT" 581 | ], 582 | "authors": [ 583 | { 584 | "name": "Daniel Bachhuber", 585 | "email": "daniel@handbuilt.co", 586 | "role": "Maintainer" 587 | }, 588 | { 589 | "name": "James Logsdon", 590 | "email": "jlogsdon@php.net", 591 | "role": "Developer" 592 | } 593 | ], 594 | "description": "Console utilities for PHP", 595 | "homepage": "http://github.com/wp-cli/php-cli-tools", 596 | "keywords": [ 597 | "cli", 598 | "console" 599 | ], 600 | "support": { 601 | "issues": "https://github.com/wp-cli/php-cli-tools/issues", 602 | "source": "https://github.com/wp-cli/php-cli-tools/tree/v0.11.22" 603 | }, 604 | "time": "2023-12-03T19:25:05+00:00" 605 | }, 606 | { 607 | "name": "wp-cli/wp-cli", 608 | "version": "v2.11.0", 609 | "source": { 610 | "type": "git", 611 | "url": "https://github.com/wp-cli/wp-cli.git", 612 | "reference": "53f0df112901fcf95099d0f501912a209429b6a9" 613 | }, 614 | "dist": { 615 | "type": "zip", 616 | "url": "https://api.github.com/repos/wp-cli/wp-cli/zipball/53f0df112901fcf95099d0f501912a209429b6a9", 617 | "reference": "53f0df112901fcf95099d0f501912a209429b6a9", 618 | "shasum": "" 619 | }, 620 | "require": { 621 | "ext-curl": "*", 622 | "mustache/mustache": "^2.14.1", 623 | "php": "^5.6 || ^7.0 || ^8.0", 624 | "symfony/finder": ">2.7", 625 | "wp-cli/mustangostang-spyc": "^0.6.3", 626 | "wp-cli/php-cli-tools": "~0.11.2" 627 | }, 628 | "require-dev": { 629 | "roave/security-advisories": "dev-latest", 630 | "wp-cli/db-command": "^1.3 || ^2", 631 | "wp-cli/entity-command": "^1.2 || ^2", 632 | "wp-cli/extension-command": "^1.1 || ^2", 633 | "wp-cli/package-command": "^1 || ^2", 634 | "wp-cli/wp-cli-tests": "^4.0.1" 635 | }, 636 | "suggest": { 637 | "ext-readline": "Include for a better --prompt implementation", 638 | "ext-zip": "Needed to support extraction of ZIP archives when doing downloads or updates" 639 | }, 640 | "bin": [ 641 | "bin/wp", 642 | "bin/wp.bat" 643 | ], 644 | "type": "library", 645 | "extra": { 646 | "branch-alias": { 647 | "dev-main": "2.11.x-dev" 648 | } 649 | }, 650 | "autoload": { 651 | "psr-0": { 652 | "WP_CLI\\": "php/" 653 | }, 654 | "classmap": [ 655 | "php/class-wp-cli.php", 656 | "php/class-wp-cli-command.php" 657 | ] 658 | }, 659 | "notification-url": "https://packagist.org/downloads/", 660 | "license": [ 661 | "MIT" 662 | ], 663 | "description": "WP-CLI framework", 664 | "homepage": "https://wp-cli.org", 665 | "keywords": [ 666 | "cli", 667 | "wordpress" 668 | ], 669 | "support": { 670 | "docs": "https://make.wordpress.org/cli/handbook/", 671 | "issues": "https://github.com/wp-cli/wp-cli/issues", 672 | "source": "https://github.com/wp-cli/wp-cli" 673 | }, 674 | "time": "2024-08-08T03:04:55+00:00" 675 | } 676 | ], 677 | "packages-dev": [], 678 | "aliases": [], 679 | "minimum-stability": "stable", 680 | "stability-flags": {}, 681 | "prefer-stable": true, 682 | "prefer-lowest": false, 683 | "platform": { 684 | "php": ">=7.0" 685 | }, 686 | "platform-dev": {}, 687 | "plugin-api-version": "2.6.0" 688 | } 689 | --------------------------------------------------------------------------------