├── .phpunit-watcher.yml ├── config ├── di-console.php └── params.php ├── infection.json.dist ├── psalm.xml ├── rector.php ├── CHANGELOG.md ├── src ├── Exception │ └── NoCategorySourceConfigException.php ├── CategorySource.php ├── Command │ └── ExtractCommand.php └── Extractor.php ├── LICENSE.md ├── .styleci.yml ├── composer.json └── README.md /.phpunit-watcher.yml: -------------------------------------------------------------------------------- 1 | watch: 2 | directories: 3 | - src 4 | - tests 5 | fileMask: '*.php' 6 | notifications: 7 | passingTests: false 8 | failingTests: false 9 | phpunit: 10 | binaryPath: vendor/bin/phpunit 11 | timeout: 180 12 | -------------------------------------------------------------------------------- /config/di-console.php: -------------------------------------------------------------------------------- 1 | [ 11 | '__construct()' => [ 12 | [], 13 | ], 14 | ], 15 | ]; 16 | -------------------------------------------------------------------------------- /config/params.php: -------------------------------------------------------------------------------- 1 | [ 9 | 'commands' => [ 10 | 'translator/extract' => ExtractCommand::class, 11 | ], 12 | ], 13 | ]; 14 | -------------------------------------------------------------------------------- /infection.json.dist: -------------------------------------------------------------------------------- 1 | { 2 | "source": { 3 | "directories": [ 4 | "src" 5 | ] 6 | }, 7 | "logs": { 8 | "text": "php:\/\/stderr", 9 | "stryker": { 10 | "report": "master" 11 | } 12 | }, 13 | "mutators": { 14 | "@default": true 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /psalm.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /rector.php: -------------------------------------------------------------------------------- 1 | paths([ 12 | __DIR__ . '/src', 13 | __DIR__ . '/tests', 14 | ]); 15 | 16 | // register a single rule 17 | $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class); 18 | 19 | // define sets of rules 20 | $rectorConfig->sets([ 21 | LevelSetList::UP_TO_PHP_80, 22 | ]); 23 | 24 | $rectorConfig->skip([ 25 | ClosureToArrowFunctionRector::class, 26 | ]); 27 | }; 28 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Yii Translator Message Extractor Change Log 2 | 3 | ## 2.1.2 under development 4 | 5 | - no changes in this release. 6 | 7 | ## 2.1.1 February 13, 2024 8 | 9 | - Enh #47: Add "dev" keyword to composer.json for suggest package to require-dev section (@samdark) 10 | 11 | ## 2.1.0 January 18, 2024 12 | 13 | - Enh #42: Add ability to change the calling method in translator extractor (@terabytesoftw) 14 | - Enh #43, #45: Add support of `symfony/console` version `^7.0` (@terabytesoftw, @vjik) 15 | 16 | ## 2.0.0 February 17, 2023 17 | 18 | - Chg #31: Adapt configuration group names to Yii conventions (@vjik) 19 | - Chg #34: Make `yiisoft/yii-console` dependency for development only (@vjik) 20 | - Enh #31: Improve solution in `NoCategorySourceConfigException` (@vjik) 21 | - Enh #33: Add support of `yiisoft/translator` version `^3.0` (@vjik) 22 | 23 | ## 1.1.0 November 08, 2022 24 | 25 | - Enh #18: Raise minimum PHP version to `^8.0` (@vjik, @xepozz) 26 | - Enh #20: Add support of `yiisoft/translator` version `^2.0` (@vjik) 27 | 28 | ## 1.0.0 December 20, 2021 29 | 30 | - Initial release. 31 | -------------------------------------------------------------------------------- /src/Exception/NoCategorySourceConfigException.php: -------------------------------------------------------------------------------- 1 | [ 29 | '__construct()' => [ 30 | DynamicReferencesArray::from([ 31 | static fn (Aliases $aliases) => new MessageSource($aliases->get('@message')), 32 | ]) 33 | ], 34 | ], 35 | ]; 36 | ``` 37 | SOLUTION; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © 2008 by Yii Software (https://www.yiiframework.com/) 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the 13 | distribution. 14 | * Neither the name of Yii Software nor the names of its 15 | contributors may be used to endorse or promote products derived 16 | from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /src/CategorySource.php: -------------------------------------------------------------------------------- 1 | name; 37 | } 38 | 39 | /** 40 | * @param string $category Category of messages to get. 41 | * @param string $locale Locale of messages to get. 42 | * 43 | * @psalm-return array> 44 | * 45 | * @return array All messages from category. The format is 46 | * the same as in {@see \Yiisoft\Translator\MessageReaderInterface::getMessages()}. 47 | */ 48 | public function readMessages(string $category, string $locale): array 49 | { 50 | return $this->reader->getMessages($category, $locale); 51 | } 52 | 53 | /** 54 | * @param string $category Category to write messages to. 55 | * @param string $locale Locale to write messages for. 56 | * @param array $messages Messages to write. 57 | * 58 | * @psalm-param array> $messages 59 | * 60 | * @see \Yiisoft\Translator\MessageWriterInterface::write 61 | */ 62 | public function writeMessages(string $category, string $locale, array $messages): void 63 | { 64 | $this->writer->write($category, $locale, $messages); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /.styleci.yml: -------------------------------------------------------------------------------- 1 | preset: psr12 2 | risky: true 3 | 4 | version: 8.1 5 | 6 | finder: 7 | exclude: 8 | - docs 9 | - vendor 10 | 11 | enabled: 12 | - alpha_ordered_traits 13 | - array_indentation 14 | - array_push 15 | - combine_consecutive_issets 16 | - combine_consecutive_unsets 17 | - combine_nested_dirname 18 | - declare_strict_types 19 | - dir_constant 20 | - fully_qualified_strict_types 21 | - function_to_constant 22 | - hash_to_slash_comment 23 | - is_null 24 | - logical_operators 25 | - magic_constant_casing 26 | - magic_method_casing 27 | - method_separation 28 | - modernize_types_casting 29 | - native_function_casing 30 | - native_function_type_declaration_casing 31 | - no_alias_functions 32 | - no_empty_comment 33 | - no_empty_phpdoc 34 | - no_empty_statement 35 | - no_extra_block_blank_lines 36 | - no_short_bool_cast 37 | - no_superfluous_elseif 38 | - no_unneeded_control_parentheses 39 | - no_unneeded_curly_braces 40 | - no_unneeded_final_method 41 | - no_unset_cast 42 | - no_unused_imports 43 | - no_unused_lambda_imports 44 | - no_useless_else 45 | - no_useless_return 46 | - normalize_index_brace 47 | - php_unit_dedicate_assert 48 | - php_unit_dedicate_assert_internal_type 49 | - php_unit_expectation 50 | - php_unit_mock 51 | - php_unit_mock_short_will_return 52 | - php_unit_namespaced 53 | - php_unit_no_expectation_annotation 54 | - phpdoc_no_empty_return 55 | - phpdoc_no_useless_inheritdoc 56 | - phpdoc_order 57 | - phpdoc_property 58 | - phpdoc_scalar 59 | - phpdoc_singular_inheritdoc 60 | - phpdoc_trim 61 | - phpdoc_trim_consecutive_blank_line_separation 62 | - phpdoc_type_to_var 63 | - phpdoc_types 64 | - phpdoc_types_order 65 | - print_to_echo 66 | - regular_callable_call 67 | - return_assignment 68 | - self_accessor 69 | - self_static_accessor 70 | - set_type_to_cast 71 | - short_array_syntax 72 | - short_list_syntax 73 | - simplified_if_return 74 | - single_quote 75 | - standardize_not_equals 76 | - ternary_to_null_coalescing 77 | - trailing_comma_in_multiline_array 78 | - unalign_double_arrow 79 | - unalign_equals 80 | - empty_loop_body_braces 81 | - integer_literal_case 82 | - union_type_without_spaces 83 | 84 | disabled: 85 | - function_declaration 86 | -------------------------------------------------------------------------------- /src/Command/ExtractCommand.php: -------------------------------------------------------------------------------- 1 | addOption('languages', 'L', InputOption::VALUE_OPTIONAL, 'Comma separated list of languages to write message sources for. By default it is `en`.', 'en') 32 | ->addOption('category', 'C', InputOption::VALUE_OPTIONAL, 'Default message category to use when category is not set.', $this->defaultCategory) 33 | ->addOption('except', 'E', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, 'Exclude path from extracting.', []) 34 | ->addOption('only', 'O', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, 'Use the only specified path for extracting.', []) 35 | ->addArgument('path', InputArgument::OPTIONAL, 'Path for extracting message IDs.') 36 | ->setHelp('This command Extracts translator IDs from files within a given path.'); 37 | } 38 | 39 | protected function execute(InputInterface $input, OutputInterface $output): int 40 | { 41 | /** @var string */ 42 | $path = $input->getArgument('path') ?? getcwd(); 43 | 44 | /** @var string */ 45 | $languages = $input->getOption('languages'); 46 | 47 | /** @var string */ 48 | $category = $input->getOption('category'); 49 | 50 | /** @var string[] */ 51 | $except = $input->getOption('except'); 52 | 53 | /** @var string[] */ 54 | $only = $input->getOption('only'); 55 | 56 | /** @var string[] */ 57 | $languagesList = explode(',', $languages); 58 | 59 | $this->extractor->setExcept($except); 60 | $this->extractor->setOnly($only); 61 | 62 | $this->extractor->process($path, $category, $languagesList, $output); 63 | 64 | return 0; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yiisoft/translator-extractor", 3 | "type": "library", 4 | "description": "Yii message extractor", 5 | "keywords": [ 6 | "i18n", 7 | "internationalization", 8 | "extractor", 9 | "dev" 10 | ], 11 | "homepage": "https://www.yiiframework.com/", 12 | "license": "BSD-3-Clause", 13 | "support": { 14 | "issues": "https://github.com/yiisoft/translator-extractor/issues?state=open", 15 | "source": "https://github.com/yiisoft/translator-extractor", 16 | "forum": "https://www.yiiframework.com/forum/", 17 | "wiki": "https://www.yiiframework.com/wiki/", 18 | "irc": "ircs://irc.libera.chat:6697/yii", 19 | "chat": "https://t.me/yii3en" 20 | }, 21 | "funding": [ 22 | { 23 | "type": "opencollective", 24 | "url": "https://opencollective.com/yiisoft" 25 | }, 26 | { 27 | "type": "github", 28 | "url": "https://github.com/sponsors/yiisoft" 29 | } 30 | ], 31 | "require": { 32 | "php": "^8.0", 33 | "symfony/console": "^5.4|^6.0|^7.0", 34 | "yiisoft/friendly-exception": "^1.0", 35 | "yiisoft/translator": "^1.0|^2.0|^3.0" 36 | }, 37 | "require-dev": { 38 | "maglnet/composer-require-checker": "^4.2", 39 | "phpunit/phpunit": "^9.5", 40 | "rector/rector": "^1.0", 41 | "roave/infection-static-analysis-plugin": "^1.16", 42 | "spatie/phpunit-watcher": "^1.23", 43 | "vimeo/psalm": "^4.30|^5.6", 44 | "yiisoft/di": "^1.0", 45 | "yiisoft/yii-console": "^2.0" 46 | }, 47 | "autoload": { 48 | "psr-4": { 49 | "Yiisoft\\TranslatorExtractor\\": "src" 50 | } 51 | }, 52 | "autoload-dev": { 53 | "psr-4": { 54 | "Yiisoft\\TranslatorExtractor\\Tests\\": "tests" 55 | } 56 | }, 57 | "extra": { 58 | "config-plugin-options": { 59 | "source-directory": "config" 60 | }, 61 | "config-plugin": { 62 | "params": "params.php", 63 | "di-console": "di-console.php" 64 | } 65 | }, 66 | "config": { 67 | "sort-packages": true, 68 | "allow-plugins": { 69 | "infection/extension-installer": true, 70 | "composer/package-versions-deprecated": true 71 | } 72 | }, 73 | "scripts": { 74 | "mutation": [ 75 | "Composer\\Config::disableProcessTimeout", 76 | "roave-infection-static-analysis-plugin" 77 | ], 78 | "psalm": "psalm", 79 | "test": "phpunit --testdox --no-interaction", 80 | "test-watch": "phpunit-watcher watch" 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/Extractor.php: -------------------------------------------------------------------------------- 1 | translate') 34 | { 35 | if (empty($categories)) { 36 | throw new NoCategorySourceConfigException(); 37 | } 38 | 39 | foreach ($categories as $category) { 40 | $this->categorySources[$category->getName()] = $category; 41 | } 42 | } 43 | 44 | /** 45 | * Set list of patterns that the files or directories should not match. 46 | * 47 | * @see PathMatcher 48 | * 49 | * @param string[] $except 50 | */ 51 | public function setExcept(array $except): void 52 | { 53 | if (!empty($except)) { 54 | $this->except = $except; 55 | } 56 | } 57 | 58 | /** 59 | * Set list of patterns that the files or directories should match. 60 | * 61 | * @see PathMatcher 62 | * 63 | * @param string[] $only 64 | */ 65 | public function setOnly(array $only): void 66 | { 67 | if (!empty($only)) { 68 | $this->only = $only; 69 | } 70 | } 71 | 72 | /** 73 | * @param string $filesPath Path to files to extract from. 74 | * @param string $defaultCategory Category to use if category isn't set in translation call. 75 | * @param string[] $languages Languages to write extracted IDs to. 76 | */ 77 | public function process(string $filesPath, string $defaultCategory, array $languages, OutputInterface $output): void 78 | { 79 | if (!isset($this->categorySources[$defaultCategory])) { 80 | $output->writeln('Default category was not found in a list of Categories.'); 81 | return; 82 | } 83 | 84 | $translationExtractor = new TranslationExtractor( 85 | $filesPath, 86 | $this->applyRoot($this->only, $filesPath), 87 | $this->applyRoot($this->except, $filesPath) 88 | ); 89 | 90 | $messagesList = $translationExtractor->extract($defaultCategory, $this->translatorCall); 91 | 92 | if (empty($messagesList)) { 93 | $output->writeln('Messages not found'); 94 | return; 95 | } 96 | 97 | $output->writeln('Languages: ' . implode(', ', $languages)); 98 | 99 | /** 100 | * @var string $categoryName 101 | * @var array|mixed> $messages 102 | */ 103 | foreach ($messagesList as $categoryName => $messages) { 104 | $output->writeln('Category: "' . $categoryName . '", messages found: ' . count($messages) . '.'); 105 | 106 | /** @var array> $convertedMessages */ 107 | $convertedMessages = $this->convert($messages); 108 | foreach ($languages as $language) { 109 | $extractCategory = isset($this->categorySources[$categoryName]) ? $categoryName : $defaultCategory; 110 | $this->addMessages($extractCategory, $language, $convertedMessages); 111 | } 112 | } 113 | } 114 | 115 | private function addMessages(string $categoryName, string $language, array $messages): void 116 | { 117 | $readMessages = $this->categorySources[$categoryName]->readMessages($categoryName, $language); 118 | /** @var array> $convertedMessages */ 119 | $convertedMessages = array_merge($messages, $readMessages); 120 | $this->categorySources[$categoryName]->writeMessages($categoryName, $language, $convertedMessages); 121 | } 122 | 123 | private function convert(array $messages): array 124 | { 125 | $returningMessages = []; 126 | 127 | /** @var array $messages */ 128 | foreach ($messages as $message) { 129 | $returningMessages[$message] = ['message' => $message]; 130 | } 131 | 132 | return $returningMessages; 133 | } 134 | 135 | /** 136 | * @param string[]|null $list 137 | * 138 | * @return string[]|null 139 | */ 140 | private function applyRoot(?array $list, string $rootFolder): ?array 141 | { 142 | if (is_array($list)) { 143 | return array_map( 144 | static fn (string $except): string => preg_replace('#^\./#', $rootFolder . '/', $except), 145 | $list 146 | ); 147 | } 148 | 149 | return $list; 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | Yii 4 | 5 |

6 |

Yii Translator Message Extractor

7 | 8 | [![Latest Stable Version](https://poser.pugx.org/yiisoft/translator-extractor/v/stable.png)](https://packagist.org/packages/yiisoft/translator-extractor) 9 | [![Total Downloads](https://poser.pugx.org/yiisoft/translator-extractor/downloads.png)](https://packagist.org/packages/yiisoft/translator-extractor) 10 | [![Build status](https://github.com/yiisoft/translator-extractor/workflows/build/badge.svg)](https://github.com/yiisoft/translator-extractor/actions?query=workflow%3Abuild) 11 | [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/yiisoft/translator-extractor/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/yiisoft/translator-extractor/?branch=master) 12 | [![Code Coverage](https://scrutinizer-ci.com/g/yiisoft/translator-extractor/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/yiisoft/translator-extractor/?branch=master) 13 | [![Mutation testing badge](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2Fyiisoft%2Ftranslator-extractor%2Fmaster)](https://dashboard.stryker-mutator.io/reports/github.com/yiisoft/translator-extractor/master) 14 | [![static analysis](https://github.com/yiisoft/translator-extractor/workflows/static%20analysis/badge.svg)](https://github.com/yiisoft/translator-extractor/actions?query=workflow%3A%22static+analysis%22) 15 | [![type-coverage](https://shepherd.dev/github/yiisoft/translator-extractor/coverage.svg)](https://shepherd.dev/github/yiisoft/translator-extractor) 16 | 17 | The package allows automatically extracting translation IDs from PHP source files and writing them to 18 | [one of the translator message sources](https://github.com/yiisoft/translator#message-sources). 19 | 20 | ## Requirements 21 | 22 | - PHP 8.0 or higher. 23 | 24 | ## Installation 25 | 26 | The package could be installed with [Composer](https://getcomposer.org): 27 | 28 | ```shell 29 | composer require yiisoft/translator-extractor 30 | ``` 31 | 32 | ## Configuration 33 | 34 | You need configure `MessageReader` and `MessageWriter` in config file of the package, `config/console/translator-extractor.php`: 35 | 36 | For example, when using PHP `MessageSource` the config will be the following using **relative path**: 37 | 38 | ```php 39 | use \Yiisoft\Translator\Message\Php\MessageSource; 40 | 41 | return [ 42 | Extractor::class => [ 43 | '__construct()' => [ 44 | [ 45 | DynamicReference::to([ 46 | 'class' => ExtractorCategorySource::class, 47 | '__construct()' => [ 48 | 'app', 49 | 'messageReader' => DynamicReference::to(static fn () => new MessageSource($params['yiisoft/translator-extractor']['messagePath'])), 50 | 'messageWriter' => DynamicReference::to(static fn () => new MessageSource($params['yiisoft/translator-extractor']['messagePath'])), 51 | ], 52 | ]), 53 | ], 54 | ], 55 | '->translate' // optional, default value for Translation call to look for. 56 | ], 57 | ]; 58 | ``` 59 | 60 | And in `params.php` file you can configure parameters of a message source: 61 | 62 | ```php 63 | return [ 64 | 'yiisoft/yii-console' => [ 65 | 'commands' => [ 66 | 'translator/extract' => ExtractCommand::class, 67 | ], 68 | ], 69 | 'yiisoft/translator-extractor' => [ 70 | // Using relative path: 71 | 'messagePath' => dirname(__DIR__, 5) . '/messages', 72 | ], 73 | ]; 74 | ``` 75 | 76 | Or if with using PHP `MessageSource` the config will be the following **using Aliases**: 77 | 78 | ```php 79 | use \Yiisoft\Translator\Message\Php\MessageSource; 80 | 81 | return [ 82 | Extractor::class => [ 83 | '__construct()' => [ 84 | [ 85 | DynamicReference::to([ 86 | 'class' => ExtractorCategorySource::class, 87 | '__construct()' => [ 88 | 'app', 89 | 'messageReader' => DynamicReference::to(static fn (Aliases $aliases) => new MessageSource($aliases->get('@message'))), 90 | 'messageWriter' => DynamicReference::to(static fn (Aliases $aliases) => new MessageSource($aliases->get('@message'))), 91 | ], 92 | ]), 93 | ], 94 | ], 95 | ], 96 | ]; 97 | ``` 98 | 99 | > **Attention**: Both `MessageReader` and `MessageWriter` should be configured for using _the same_ `MessageSource`. The extractor needs it to work with existing messages. 100 | 101 | ## General usage 102 | 103 | ```shell 104 | ./yii translator/extract 105 | ``` 106 | 107 | This command will recursively find all messages in the code starting with the current directory and will save it into 108 | a message source for default language `en`. You can specify the path explicitly: 109 | 110 | ```shell 111 | ./yii translator/extract /path/to/your/project 112 | ``` 113 | 114 | **Notice:** By default extractor has `vendor` directory in the application directory excluded. To include it you can specify empty value for `except`: 115 | 116 | ```shell 117 | ./yii translator/extract /path/to/your/project --except='' 118 | ``` 119 | 120 | Full list of options: 121 | 122 | ```shell 123 | Usage: 124 | translator/extract [options] [--] [] 125 | 126 | Arguments: 127 | path Path for extracting message IDs. 128 | 129 | Options: 130 | -L, --languages=LANGUAGES Comma separated list of languages to write message sources for. By default it is `en`. [default: "en"] 131 | -C, --category=CATEGORY Default message category to use when category is not set. [default: "app"] 132 | -E, --except[=EXCEPT] Exclude path from extracting. (multiple values allowed) 133 | -O, --only[=ONLY] Use the only specified path for extracting. (multiple values allowed) 134 | 135 | ``` 136 | 137 | ### Specify languages 138 | 139 | You can specify multiple languages to write IDs into: 140 | 141 | ```shell 142 | ./yii translator/extract --languages=en,ru 143 | ``` 144 | 145 | Or in short format: 146 | 147 | ```shell 148 | ./yii translator/extract -Lru 149 | ``` 150 | 151 | ### Specify default category 152 | 153 | Also, you can specify default message category to use when category is not set. 154 | 155 | ```shell 156 | ./yii translator/extract --category=your_category_name 157 | ``` 158 | 159 | ### Using `except` option 160 | 161 | To exclude all directories named `dir1` use `--except`: 162 | 163 | ```shell 164 | ./yii translator/extract --except=**/dir1/** 165 | ``` 166 | 167 | To exclude both `vendor` and `tests` directories the following options could be used: 168 | 169 | ```shell 170 | ./yii translator/extract --except=./vendor/** --except=./tests/** 171 | ``` 172 | 173 | ### Using `only` option 174 | 175 | To parse only `test.php` files in any directory use `--only` option: 176 | 177 | ```shell 178 | ./yii translator/extract --only=**/test.php 179 | ``` 180 | 181 | To parse only `/var/www/html/test.php` file use: 182 | 183 | ```shell 184 | ./yii translator/extract --only=/var/www/html/test.php 185 | ``` 186 | 187 | For more info about `except` and `only` parameters check documentation of 188 | [yiisoft/files package](https://github.com/yiisoft/files). 189 | 190 | ## Working with gettext 191 | 192 | The package currently does not support extracting messages into gettext format. To extract messages for gettext, 193 | you may use the following shell script (in Linux-based OS): 194 | 195 | ```shell 196 | find src/ -name *.php | xargs xgettext --from-code=utf-8 --language=PHP --no-location --omit-header --sort-output --keyword=translate --output="locales/category.pot" 197 | 198 | for d in locales/*/ ; do 199 | for i in locales/*.pot; do 200 | if [ ! -f "$d$(basename "$i" .pot).po" ]; then 201 | touch "$d$(basename "$i" .pot).po" 202 | fi 203 | 204 | msgmerge --update --silent --backup=off "$d$(basename "$i" .pot).po" $i 205 | done 206 | done 207 | ``` 208 | 209 | ## Documentation 210 | 211 | - [Internals](docs/internals.md) 212 | 213 | If you need help or have a question, the [Yii Forum](https://forum.yiiframework.com/c/yii-3-0/63) is a good place for that. 214 | You may also check out other [Yii Community Resources](https://www.yiiframework.com/community). 215 | 216 | ## License 217 | 218 | The Yii Translator Message Extractor is free software. It is released under the terms of the BSD License. Please 219 | see [`LICENSE`](./LICENSE.md) for more information. 220 | 221 | Maintained by [Yii Software](https://www.yiiframework.com/). 222 | 223 | ## Support the project 224 | 225 | [![Open Collective](https://img.shields.io/badge/Open%20Collective-sponsor-7eadf1?logo=open%20collective&logoColor=7eadf1&labelColor=555555)](https://opencollective.com/yiisoft) 226 | 227 | ## Follow updates 228 | 229 | [![Official website](https://img.shields.io/badge/Powered_by-Yii_Framework-green.svg?style=flat)](https://www.yiiframework.com/) 230 | [![Twitter](https://img.shields.io/badge/twitter-follow-1DA1F2?logo=twitter&logoColor=1DA1F2&labelColor=555555?style=flat)](https://twitter.com/yiiframework) 231 | [![Telegram](https://img.shields.io/badge/telegram-join-1DA1F2?style=flat&logo=telegram)](https://t.me/yii3en) 232 | [![Facebook](https://img.shields.io/badge/facebook-join-1DA1F2?style=flat&logo=facebook&logoColor=ffffff)](https://www.facebook.com/groups/yiitalk) 233 | [![Slack](https://img.shields.io/badge/slack-join-1DA1F2?style=flat&logo=slack)](https://yiiframework.com/go/slack) 234 | --------------------------------------------------------------------------------