Browse Source

Update Gettext library

Relates to #254.
pull/257/head
Trevor Slocum 5 months ago
parent
commit
0b02c3fdb5
  1. 10
      imgboard.php
  2. 18
      inc/gettext.php
  3. 223
      inc/gettext/CHANGELOG.md
  4. 2
      inc/gettext/LICENSE
  5. 405
      inc/gettext/README.md
  6. 26
      inc/gettext/composer.json
  7. 39
      inc/gettext/src/BaseTranslator.php
  8. 89
      inc/gettext/src/Comments.php
  9. 29
      inc/gettext/src/Extractors/Blade.php
  10. 53
      inc/gettext/src/Extractors/Csv.php
  11. 47
      inc/gettext/src/Extractors/CsvDictionary.php
  12. 80
      inc/gettext/src/Extractors/Extractor.php
  13. 26
      inc/gettext/src/Extractors/ExtractorInterface.php
  14. 28
      inc/gettext/src/Extractors/ExtractorMultiInterface.php
  15. 55
      inc/gettext/src/Extractors/Jed.php
  16. 74
      inc/gettext/src/Extractors/JsCode.php
  17. 26
      inc/gettext/src/Extractors/Json.php
  18. 26
      inc/gettext/src/Extractors/JsonDictionary.php
  19. 131
      inc/gettext/src/Extractors/Mo.php
  20. 33
      inc/gettext/src/Extractors/PhpArray.php
  21. 170
      inc/gettext/src/Extractors/PhpCode.php
  22. 211
      inc/gettext/src/Extractors/Po.php
  23. 45
      inc/gettext/src/Extractors/Twig.php
  24. 423
      inc/gettext/src/Extractors/VueJs.php
  25. 86
      inc/gettext/src/Extractors/Xliff.php
  26. 27
      inc/gettext/src/Extractors/Yaml.php
  27. 27
      inc/gettext/src/Extractors/YamlDictionary.php
  28. 96
      inc/gettext/src/Flags.php
  29. 18
      inc/gettext/src/Generator/Generator.php
  30. 13
      inc/gettext/src/Generator/GeneratorInterface.php
  31. 69
      inc/gettext/src/Generator/MoGenerator.php
  32. 134
      inc/gettext/src/Generator/PoGenerator.php
  33. 56
      inc/gettext/src/Generators/Csv.php
  34. 39
      inc/gettext/src/Generators/CsvDictionary.php
  35. 22
      inc/gettext/src/Generators/Generator.php
  36. 29
      inc/gettext/src/Generators/GeneratorInterface.php
  37. 66
      inc/gettext/src/Generators/Jed.php
  38. 26
      inc/gettext/src/Generators/Json.php
  39. 26
      inc/gettext/src/Generators/JsonDictionary.php
  40. 40
      inc/gettext/src/Generators/PhpArray.php
  41. 145
      inc/gettext/src/Generators/Po.php
  42. 122
      inc/gettext/src/Generators/Xliff.php
  43. 32
      inc/gettext/src/Generators/Yaml.php
  44. 32
      inc/gettext/src/Generators/YamlDictionary.php
  45. 161
      inc/gettext/src/GettextTranslator.php
  46. 144
      inc/gettext/src/Headers.php
  47. 56
      inc/gettext/src/Loader/Loader.php
  48. 13
      inc/gettext/src/Loader/LoaderInterface.php
  49. 142
      inc/gettext/src/Loader/MoLoader.php
  50. 226
      inc/gettext/src/Loader/PoLoader.php
  51. 243
      inc/gettext/src/Merge.php
  52. 89
      inc/gettext/src/References.php
  53. 171
      inc/gettext/src/Scanner/CodeScanner.php
  54. 145
      inc/gettext/src/Scanner/FunctionsHandlersTrait.php
  55. 12
      inc/gettext/src/Scanner/FunctionsScannerInterface.php
  56. 105
      inc/gettext/src/Scanner/ParsedFunction.php
  57. 88
      inc/gettext/src/Scanner/Scanner.php
  58. 22
      inc/gettext/src/Scanner/ScannerInterface.php
  59. 543
      inc/gettext/src/Translation.php
  60. 530
      inc/gettext/src/Translations.php
  61. 270
      inc/gettext/src/Translator.php
  62. 112
      inc/gettext/src/TranslatorInterface.php
  63. 56
      inc/gettext/src/Utils/CsvTrait.php
  64. 59
      inc/gettext/src/Utils/DictionaryTrait.php
  65. 167
      inc/gettext/src/Utils/FunctionsScanner.php
  66. 67
      inc/gettext/src/Utils/HeadersExtractorTrait.php
  67. 29
      inc/gettext/src/Utils/HeadersGeneratorTrait.php
  68. 320
      inc/gettext/src/Utils/JsFunctionsScanner.php
  69. 100
      inc/gettext/src/Utils/MultidimensionalArrayTrait.php
  70. 140
      inc/gettext/src/Utils/ParsedComment.php
  71. 159
      inc/gettext/src/Utils/ParsedFunction.php
  72. 194
      inc/gettext/src/Utils/PhpFunctionsScanner.php
  73. 51
      inc/gettext/src/Utils/StringReader.php
  74. 14
      inc/gettext/src/autoloader.php
  75. 191
      inc/gettext/src/translator_functions.php

10
imgboard.php

@ -26,9 +26,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
use Gettext\Translator;
use Gettext\Translations;
error_reporting(E_ALL);
ini_set("display_errors", 1);
session_start();
@ -58,12 +55,7 @@ if (!defined('TINYIB_LOCALE') || TINYIB_LOCALE == '') {
return $string;
}
} else {
setlocale(LC_ALL, TINYIB_LOCALE);
require 'inc/gettext/src/autoloader.php';
$translations = Translations::fromPoFile('locale/' . TINYIB_LOCALE . '/tinyib.po');
$translator = new Translator();
$translator->loadTranslations($translations);
$translator->register();
require 'inc/gettext.php';
}
if ((TINYIB_CAPTCHA === 'hcaptcha' || TINYIB_REPLYCAPTCHA === 'hcaptcha' || TINYIB_MANAGECAPTCHA === 'hcaptcha') && (TINYIB_HCAPTCHA_SITE == '' || TINYIB_HCAPTCHA_SECRET == '')) {

18
inc/gettext.php

@ -0,0 +1,18 @@
<?php
use Gettext\Loader\PoLoader;
require 'inc/gettext/src/autoloader.php';
setlocale(LC_ALL, TINYIB_LOCALE);
$loader = new PoLoader();
$translations = $loader->loadFile('locale/' . TINYIB_LOCALE . '/tinyib.po');
function __($string) {
global $translations;
$translation = $translations->find(null, $string)->getTranslation();
if ($translation == '') {
return $string;
}
return $translation;
}

223
inc/gettext/CHANGELOG.md

@ -7,166 +7,123 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
Previous releases are documented in [github releases](https://github.com/oscarotero/Gettext/releases)
## [4.8.2] - 2019-12-02
## [5.6.1] - 2021-12-04
### Fixed
- UTF-8 handling for VueJs extractor [#242]
- PHP 8.1 support [#278].
## [4.8.1] - 2019-11-15
### Fixed
- Php error when scanning for a single domain but other string found [#238]
## [4.8.0] - 2019-11-04
### Changed
- Many `private` properties and methods were changed to `protected` in order to improve the extensibility [#231]
### Fixed
- PHP 7.4 support [#230]
## [4.7.0] - 2019-10-07
## [5.6.0] - 2021-11-05
### Added
- Support for UnitID in Xliff [#221] [#224] [#225]
- Support for scan multiple domains at the same time [#223]
- New method `addFlag` to `ParsedFunction`, that allows to assign flags by scanners.
- The `FunctionsHandlersTrait` has an abstract `addFlags` method.
### Fixed
- New lines in windows [#218] [#226]
## [4.6.3] - 2019-07-15
### Added
- Some VueJs extraction improvements and additions [#205], [#213]
- Subsequent load file fails [#257] [#276]
- Upgraded some dependencies in `dev`.
## [5.5.4] - 2020-12-20
### Fixed
- Multiline extractions in jsCode [#200]
- Support for js template literals [#214]
- Fixed tabs in PHP comments [#215]
## [4.6.2] - 2019-01-12
### Added
- New option `facade` in blade extractor to use a facade instead create a blade compiler [#197], [#198]
- TypeError in which numeric entries were converted to integers [#265]
## [5.5.3] - 2020-12-01
### Fixed
- Added php-7.3 to travis
- Added VueJS extractor method docblocks for IDEs [#191]
- Add PHP 8 to composer.json
## [4.6.1] - 2018-08-27
## [5.5.2] - 2020-11-17
### Fixed
- VueJS DOM parsing [#188]
- Javascript parser was unable to extract some functions [#187]
## [4.6.0] - 2018-06-26
### Added
- New extractor for VueJs [#178]
- Parse of multiline disabled translations [#262] [#263]
## [5.5.1] - 2020-06-08
### Fixed
- Do not include empty translations containing the headers in the translator [#182]
- Test enhancement [#177]
- Type error in which numeric filenames were converted to integers [#260]
## [4.5.0] - 2018-04-23
## [5.5.0] - 2020-05-23
### Added
- Support for disabled translations
- New option `addReferences()` to configure the code scanners whether add or not references [#258]
### Changed
- BREAKING: Moved some code from `CodeScanner` to the new `FunctionsHandlersTrait` in order to better reuse.
## [5.4.1] - 2020-03-15
### Fixed
- Added php-7.2 to travis
- Fixed po tests on bigendian [#159]
- Improved comment estraction [#166]
- Fixed incorrect docs to dn__ function [#170]
- Ignored phpcs.xml file on export [#168]
- Improved `@method` docs in `Translations` [#175]
## [4.4.4] - 2018-02-21
### Fixed
- Changed the comment extraction to be compatible with gettext behaviour: the comment must be placed in the line preceding the function [#161]
- PoGenerator includes the description and flags of the translations [#253]
### Security
- Validate eval input from plural forms [#156]
## [5.4.0] - 2020-03-07
### Added
- Added `_` function to the list of functions scanned by default
- Added `Translations::setDescription()` and `Translations::getDescription()` methods [#251]
- Added `Translations::getFlags()` that returns a `Flags` object to assign flags to the entire po file [#251]
## [4.4.3] - 2017-08-09
### Fixed
- Handle `NULL` arguments on extract entries in php. For example `dn__(null, 'singular', 'plural')`.
- Fixed the `PhpCode` and `JsCode` extractors that didn't extract `dn__` and `dngettext` entries [#155].
- Fixed the `PhpCode` and `JsCode` extractors that didn't extract `dnpgettext` correctly.
## [5.3.0] - 2020-02-18
### Added
- `Comments::delete()` and `Flags::delete()` methods [#247]
## [4.4.2] - 2017-07-27
## [5.2.2] - 2020-02-09
### Fixed
- Clone the translations in `Translations::mergeWith` to prevent that the translation is referenced in both places. [#152]
- Fixed escaped quotes in the javascript extractor [#154]
- MoLoader with plurals [#246]
## [4.4.1] - 2017-05-20
## [5.2.1] - 2019-12-08
### Fixed
- Fixed a bug where the options was not passed correctly to the merging Translations object [#147]
- Unified the plural behaviours between PHP gettext and Translator when the plural translation is unknown [#148]
- Removed the deprecated function `create_function()` and use `eval()` instead
- Multiline string in PoGenerator [#244]
## [4.4.0] - 2017-05-10
## [5.2.0] - 2019-11-25
### Added
- New option `noLocation` to po generator, to omit the references [#143]
- New options `delimiter`, `enclosure` and `escape_char` to Csv and CsvDictionary extractors and generators [#145]
- Added the missing `dn__()` function [#146]
- New function `CodeScanner::extractCommentsStartingWith()` to extract comments from the code.
### Fixed
- Improved the code style including php_codesniffer in development
## [5.1.0] - 2019-11-11
### Added
- New function `CodeScanner::ignoreInvalidFunctions()` to ignore invalid functions instead throw an exception
## 4.3.0 - 2017-03-04
## 5.0.0 - 2019-11-04
### Added
- Added support for named placeholders (using `strtr`). For example:
```php
__('Hello :name', [':name' => 'World']);
```
- Added support for Twig v2
- New function `BaseTranslator::includeFunctions()` to include the functions file without register any translator
- New interfaces: `ScannerInterface` and `FunctionsScannerInterface`.
### Changed
- Moved the package and dependencies to [php-gettext](https://github.com/php-gettext) organization
- Minimum PHP version supported is 7.2
- Added php7 strict typing
- Extractors have been split into two different types of classes to import translations:
- Scanners: To scan code files (like php, javascript, twig, etc) in order to collect gettext entries from many domains at the same time.
- Loaders: To load a translation format such po, mo, json, xliff, etc
- Split the `Translation` and `Translations` classes in different sub-classes to handle comments, flags, references, etc. For example, instead `$translation->addComment('foo')` now it's `$translation->getComments()->add('foo')`.
- Simplified the options to merge translations with pre-configured options like `Merged::SCAN_AND_LOAD`.
- The headers of translations are always sorted alphabetically.
- Changed the signature of all classes and interfaces.
### Removed
- Extractors (now scanners and loaders), generators and translators were removed from this package and published as external packages, allowing to install only those that you need. Only Po and Mo formats are included by default.
- Removed magic classes like `Translations::fromPoFile` or `$translation->toMoFile()`. Now, the scanners, loaders and generators are independent classes that have to be instantiated.
- Removed `Merge::LANGUAGE_OVERRIDE` and `Merge::DOMAIN_OVERRIDE` contants
### Fixed
- Fixed a bug related with the javascript source extraction with single quotes
[#143]: https://github.com/oscarotero/Gettext/issues/143
[#145]: https://github.com/oscarotero/Gettext/issues/145
[#146]: https://github.com/oscarotero/Gettext/issues/146
[#147]: https://github.com/oscarotero/Gettext/issues/147
[#148]: https://github.com/oscarotero/Gettext/issues/148
[#152]: https://github.com/oscarotero/Gettext/issues/152
[#154]: https://github.com/oscarotero/Gettext/issues/154
[#155]: https://github.com/oscarotero/Gettext/issues/155
[#156]: https://github.com/oscarotero/Gettext/issues/156
[#159]: https://github.com/oscarotero/Gettext/issues/159
[#161]: https://github.com/oscarotero/Gettext/issues/161
[#166]: https://github.com/oscarotero/Gettext/issues/166
[#168]: https://github.com/oscarotero/Gettext/issues/168
[#170]: https://github.com/oscarotero/Gettext/issues/170
[#175]: https://github.com/oscarotero/Gettext/issues/175
[#177]: https://github.com/oscarotero/Gettext/issues/177
[#178]: https://github.com/oscarotero/Gettext/issues/178
[#182]: https://github.com/oscarotero/Gettext/issues/182
[#187]: https://github.com/oscarotero/Gettext/issues/187
[#188]: https://github.com/oscarotero/Gettext/issues/188
[#191]: https://github.com/oscarotero/Gettext/issues/191
[#197]: https://github.com/oscarotero/Gettext/issues/197
[#198]: https://github.com/oscarotero/Gettext/issues/198
[#200]: https://github.com/oscarotero/Gettext/issues/200
[#205]: https://github.com/oscarotero/Gettext/issues/205
[#213]: https://github.com/oscarotero/Gettext/issues/213
[#214]: https://github.com/oscarotero/Gettext/issues/214
[#215]: https://github.com/oscarotero/Gettext/issues/215
[#218]: https://github.com/oscarotero/Gettext/issues/218
[#221]: https://github.com/oscarotero/Gettext/issues/221
[#223]: https://github.com/oscarotero/Gettext/issues/223
[#224]: https://github.com/oscarotero/Gettext/issues/224
[#225]: https://github.com/oscarotero/Gettext/issues/225
[#226]: https://github.com/oscarotero/Gettext/issues/226
[#230]: https://github.com/oscarotero/Gettext/issues/230
[#231]: https://github.com/oscarotero/Gettext/issues/231
[#238]: https://github.com/oscarotero/Gettext/issues/238
[#242]: https://github.com/oscarotero/Gettext/issues/242
[4.8.2]: https://github.com/oscarotero/Gettext/compare/v4.8.1...v4.8.2
[4.8.1]: https://github.com/oscarotero/Gettext/compare/v4.8.0...v4.8.1
[4.8.0]: https://github.com/oscarotero/Gettext/compare/v4.7.0...v4.8.0
[4.7.0]: https://github.com/oscarotero/Gettext/compare/v4.6.3...v4.7.0
[4.6.3]: https://github.com/oscarotero/Gettext/compare/v4.6.2...v4.6.3
[4.6.2]: https://github.com/oscarotero/Gettext/compare/v4.6.1...v4.6.2
[4.6.1]: https://github.com/oscarotero/Gettext/compare/v4.6.0...v4.6.1
[4.6.0]: https://github.com/oscarotero/Gettext/compare/v4.5.0...v4.6.0
[4.5.0]: https://github.com/oscarotero/Gettext/compare/v4.4.4...v4.5.0
[4.4.4]: https://github.com/oscarotero/Gettext/compare/v4.4.3...v4.4.4
[4.4.3]: https://github.com/oscarotero/Gettext/compare/v4.4.2...v4.4.3
[4.4.2]: https://github.com/oscarotero/Gettext/compare/v4.4.1...v4.4.2
[4.4.1]: https://github.com/oscarotero/Gettext/compare/v4.4.0...v4.4.1
[4.4.0]: https://github.com/oscarotero/Gettext/compare/v4.3.0...v4.4.0
- Improved code quality
- The library is easier to extend
- Translation id can be independent of the context + original values, in order to be more compatible with Xliff format.
[#244]: https://github.com/php-gettext/Gettext/issues/244
[#246]: https://github.com/php-gettext/Gettext/issues/246
[#247]: https://github.com/php-gettext/Gettext/issues/247
[#251]: https://github.com/php-gettext/Gettext/issues/251
[#253]: https://github.com/php-gettext/Gettext/issues/253
[#257]: https://github.com/php-gettext/Gettext/issues/257
[#258]: https://github.com/php-gettext/Gettext/issues/258
[#260]: https://github.com/php-gettext/Gettext/issues/260
[#262]: https://github.com/php-gettext/Gettext/issues/262
[#263]: https://github.com/php-gettext/Gettext/issues/263
[#265]: https://github.com/php-gettext/Gettext/issues/265
[#276]: https://github.com/php-gettext/Gettext/issues/276
[#278]: https://github.com/php-gettext/Gettext/issues/278
[5.6.1]: https://github.com/php-gettext/Gettext/compare/v5.6.0...v5.6.1
[5.6.0]: https://github.com/php-gettext/Gettext/compare/v5.5.4...v5.6.0
[5.5.4]: https://github.com/php-gettext/Gettext/compare/v5.5.3...v5.5.4
[5.5.3]: https://github.com/php-gettext/Gettext/compare/v5.5.2...v5.5.3
[5.5.2]: https://github.com/php-gettext/Gettext/compare/v5.5.1...v5.5.2
[5.5.1]: https://github.com/php-gettext/Gettext/compare/v5.5.0...v5.5.1
[5.5.0]: https://github.com/php-gettext/Gettext/compare/v5.4.1...v5.5.0
[5.4.1]: https://github.com/php-gettext/Gettext/compare/v5.4.0...v5.4.1
[5.4.0]: https://github.com/php-gettext/Gettext/compare/v5.3.0...v5.4.0
[5.3.0]: https://github.com/php-gettext/Gettext/compare/v5.2.2...v5.3.0
[5.2.2]: https://github.com/php-gettext/Gettext/compare/v5.2.1...v5.2.2
[5.2.1]: https://github.com/php-gettext/Gettext/compare/v5.2.0...v5.2.1
[5.2.0]: https://github.com/php-gettext/Gettext/compare/v5.1.0...v5.2.0
[5.1.0]: https://github.com/php-gettext/Gettext/compare/v5.0.0...v5.1.0

2
inc/gettext/LICENSE

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2017 Oscar Otero Marzoa
Copyright (c) 2019 Oscar Otero Marzoa
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

405
inc/gettext/README.md

@ -1,134 +1,68 @@
Gettext
=======
# Gettext
[![Build Status](https://travis-ci.org/oscarotero/Gettext.png?branch=master)](https://travis-ci.org/oscarotero/Gettext)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/oscarotero/Gettext/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/oscarotero/Gettext/?branch=master)
[![Latest Stable Version](https://poser.pugx.org/gettext/gettext/v/stable.svg)](https://packagist.org/packages/gettext/gettext)
[![Total Downloads](https://poser.pugx.org/gettext/gettext/downloads.svg)](https://packagist.org/packages/gettext/gettext)
[![Monthly Downloads](https://poser.pugx.org/gettext/gettext/d/monthly.png)](https://packagist.org/packages/gettext/gettext)
[![License](https://poser.pugx.org/gettext/gettext/license.svg)](https://packagist.org/packages/gettext/gettext)
[![Latest Version on Packagist][ico-version]][link-packagist]
[![Software License][ico-license]](LICENSE)
![ico-ga]
[![Total Downloads][ico-downloads]][link-downloads]
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/496dc2a6-43be-4046-a283-f8370239dd47/big.png)](https://insight.sensiolabs.com/projects/496dc2a6-43be-4046-a283-f8370239dd47)
> Note: this is the documentation of the new 5.x version. Go to [4.x branch](https://github.com/php-gettext/Gettext/tree/4.x) if you're looking for the old 4.x version
Created by Oscar Otero <http://oscarotero.com> <oom@oscarotero.com> (MIT License)
Gettext is a PHP (>=5.4) library to import/export/edit gettext from PO, MO, PHP, JS files, etc.
Gettext is a PHP (^7.2) library to import/export/edit gettext from PO, MO, PHP, JS files, etc.
## Installation
With composer (recomended):
```
composer require gettext/gettext
```
If you don't use composer in your project, you have to download and place this package in a directory of your project. You need to install also [gettext/languages](https://github.com/mlocati/cldr-to-gettext-plural-rules). Then, include the autoloaders of both projects in any place of your php code:
```php
include_once "libs/gettext/src/autoloader.php";
include_once "libs/cldr-to-gettext-plural-rules/src/autoloader.php";
```
## Classes and functions
This package contains the following classes:
* `Gettext\Translation` - A translation definition
* `Gettext\Translations` - A collection of translations
* `Gettext\Extractors\*` - Import translations from various sources (po, mo, php, js, etc)
* `Gettext\Generators\*` - Export translations to various formats (po, mo, php, json, etc)
* `Gettext\Translator` - To use the translations in your php templates instead the [gettext extension](http://php.net/gettext)
* `Gettext\GettextTranslator` - To use the [gettext extension](http://php.net/gettext)
* `Gettext\Translations` - A collection of translations (under the same domain)
* `Gettext\Scanner\*` - Scan files to extract translations (php, js, twig templates, ...)
* `Gettext\Loader\*` - Load translations from different formats (po, mo, json, ...)
* `Gettext\Generator\*` - Export translations to various formats (po, mo, json, ...)
## Usage example
```php
use Gettext\Translations;
use Gettext\Loader\PoLoader;
use Gettext\Generator\MoGenerator;
//import from a .po file:
$translations = Translations::fromPoFile('locales/gl.po');
$loader = new PoLoader();
$translations = $loader->loadFile('locales/gl.po');
//edit some translations:
$translation = $translations->find(null, 'apple');
if ($translation) {
$translation->setTranslation('Mazá');
$translation->translate('Mazá');
}
//export to a php array:
$translations->toPhpArrayFile('locales/gl.php');
//and to a .mo file
$translations->toMoFile('Locale/gl/LC_MESSAGES/messages.mo');
```
If you want use this translations in your php templates without using the gettext extension:
```php
use Gettext\Translator;
//Create the translator instance
$t = new Translator();
//Load your translations (exported as PhpArray):
$t->loadTranslations('locales/gl.php');
//Use it:
echo $t->gettext('apple'); // "Mazá"
//If you want use global functions:
$t->register();
echo __('apple'); // "Mazá"
```
To use this translations with the gettext extension:
```php
use Gettext\GettextTranslator;
//Create the translator instance
$t = new GettextTranslator();
//Set the language and load the domain
$t->setLanguage('gl');
$t->loadDomain('messages', 'Locale');
//Use it:
echo $t->gettext('apple'); // "Mazá"
//Or use the gettext functions
echo gettext('apple'); // "Mazá"
//If you want use the global functions
$t->register();
echo __('apple'); // "Mazá"
//And use sprintf/strtr placeholders
echo __('Hello %s', 'world'); //Hello world
echo __('Hello {name}', ['{name}' => 'world']); //Hello world
//export to a .mo file:
$generator = new MoGenerator();
$generator->generateFile($translations, 'Locale/gl/LC_MESSAGES/messages.mo');
```
The benefits of using the functions provided by this library (`__()` instead `_()` or `gettext()`) are:
* You are using the same functions, no matter whether the translations are provided by gettext extension or any other method.
* You can use variables easier because `sprintf` functionality is included. For example: `__('Hello %s', 'world')` instead `sprintf(_('Hello %s'), 'world')`.
* You can also use named placeholders if the second argument is an array. For example: `__('Hello %name%', ['%name%' => 'world'])` instead of `strtr(_('Hello %name%'), ['%name%' => 'world'])`.
## Translation
The `Gettext\Translation` class stores all information about a translation: the original text, the translated text, source references, comments, etc.
```php
// __construct($context, $original, $plural)
$translation = new Gettext\Translation('comments', 'One comment', '%s comments');
use Gettext\Translation;
$translation = Translation::create('comments', 'One comment', '%s comments');
$translation->setTranslation('Un comentario');
$translation->setPluralTranslation('%s comentarios');
$translation->translate('Un comentario');
$translation->translatePlural('%s comentarios');
$translation->addReference('templates/comments/comment.php', 34);
$translation->addComment('To display the amount of comments in a post');
$translation->getReferences()->add('templates/comments/comment.php', 34);
$translation->getComments()->add('To display the amount of comments in a post');
echo $translation->getContext(); // comments
echo $translation->getOriginal(); // One comment
@ -142,223 +76,134 @@ echo $translation->getTranslation(); // Un comentario
The `Gettext\Translations` class stores a collection of translations:
```php
$translations = new Gettext\Translations();
use Gettext\Translations;
//You can add new translations using the array syntax
$translations[] = new Gettext\Translation('comments', 'One comment', '%s comments');
$translations = Translations::create('my-domain');
//Or using the "insert" method
$insertedTranslation = $translations->insert('comments', 'One comment', '%s comments');
//You can add new translations:
$translation = Translation::create('comments', 'One comment', '%s comments');
$translations->add($translation);
//Find a specific translation
$translation = $translations->find('comments', 'One comment');
//Edit headers, domain, etc
$translations->setHeader('Last-Translator', 'Oscar Otero');
$translations->getHeaders()->set('Last-Translator', 'Oscar Otero');
$translations->setDomain('my-blog');
```
## Extractors
## Loaders
The extrators allows to fetch gettext values from any source. For example, to scan a .po file:
The loaders allows to get gettext values from any format. For example, to load a .po file:
```php
$translations = new Gettext\Translations();
use Gettext\Loader\PoLoader;
$loader = new PoLoader();
//From a file
Gettext\Extractors\Po::fromFile('locales/en.po', $translations);
$translations = $loader->loadFile('locales/en.po');
//From a string
$string = file_get_contents('locales2/en.po');
Gettext\Extractors\Po::fromString($string, $translations);
$translations = $loader->loadString($string);
```
The better way to use extractors is using the magic methods of `Gettext\Translations`:
This package includes the following loaders:
```php
//Create a Translations instance using a po file
$translations = Gettext\Translations::fromPoFile('locales/en.po');
- `MoLoader`
- `PoLoader`
//Add more messages from other files
$translations->addFromPoFile('locales2/en.po');
```
And you can install other formats with loaders and generators:
The available extractors are the following:
Name | Description | Example
---- | ----------- | --------
**Blade** | Scans a Blade template (For laravel users). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/blade/input.php)
**Csv** | Gets the messages from csv. | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Csv.csv)
**CsvDictionary** | Gets the messages from csv (without plurals and context). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/CsvDictionary.csv)
**Jed** | Gets the messages from a json compatible with [Jed](http://slexaxton.github.com/Jed/). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Jed.json)
**JsCode** | Scans javascript code looking for all gettext functions (the same than PhpCode but for javascript). You can use [the javascript gettext-translator library](https://github.com/oscarotero/gettext-translator) | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/jscode/input.js)
**Json** | Gets the messages from json compatible with [gettext-translator](https://github.com/oscarotero/gettext-translator). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Json.json)
**JsonDictionary** | Gets the messages from a json (without plurals and context). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/JsonDictionary.json)
**Mo** | Gets the messages from MO. | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Mo.mo)
**PhpArray** | Gets the messages from a php file that returns an array. | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/PhpArray.php)
**PhpCode** | Scans php code looking for all gettext functions (see `translator_functions.php`). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/phpcode/input.php)
**Po** | Gets the messages from PO. | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Po.po)
**Twig** | To scan a Twig template. | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/twig/input.php)
**Xliff** | Gets the messages from [xliff (2.0)](http://docs.oasis-open.org/xliff/xliff-core/v2.0/os/xliff-core-v2.0-os.html). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Xliff.xlf)
**Yaml** | Gets the messages from yaml. | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Yaml.yml)
**YamlDictionary** | Gets the messages from a yaml (without plurals and context). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/YamlDictionary.yml)
**VueJs** | Gets the messages from a VueJs template. | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/vuejs/input.vue)
- [Json](https://github.com/php-gettext/Json)
## Generators
The generators export a `Gettext\Translations` instance to any format (po, mo, array, etc).
The generators export a `Gettext\Translations` instance to any format (po, mo, etc).
```php
//Save to a file
Gettext\Generators\Po::toFile($translations, 'locales/en.po');
use Gettext\Loader\PoLoader;
use Gettext\Generator\MoGenerator;
//Return as a string
$content = Gettext\Generators\Po::toString($translations);
file_put_contents('locales/en.po', $content);
```
//Load a PO file
$poLoader = new PoLoader();
Like extractors, the better way to use generators is using the magic methods of `Gettext\Translations`:
$translations = $poLoader->loadFile('locales/en.po');
```php
//Extract messages from a php code file
$translations = Gettext\Translations::fromPhpCodeFile('templates/index.php');
//Save to MO file
$moGenerator = new MoGenerator();
//Export to a po file
$translations->toPoFile('locales/en.po');
$moGenerator->generateFile($translations, 'locales/en.mo');
//Export to a po string
$content = $translations->toPoString();
file_put_contents('locales/en.po', $content);
//Or return as a string
$content = $moGenerator->generateString($translations);
file_put_contents('locales/en.mo', $content);
```
The available generators are the following:
Name | Description | Example
---- | ----------- | --------
**Csv** | Exports to csv. | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Csv.csv)
**CsvDictionary** | Exports to csv (without plurals and context). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/CsvDictionary.csv)
**Json** | Exports to json, compatible with [gettext-translator](https://github.com/oscarotero/gettext-translator). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Json.json)
**JsonDictionary** | Exports to json (without plurals and context). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/JsonDictionary.json)
**Mo** | Exports to Mo. | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Mo.mo)
**PhpArray** | Exports to php code that returns an array. | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/PhpArray.php)
**Po** | Exports to Po. | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Po.po)
**Jed** | Exports to json format compatible with [Jed](http://slexaxton.github.com/Jed/). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Jed.json)
**Xliff** | Exports to [xliff (2.0)](http://docs.oasis-open.org/xliff/xliff-core/v2.0/os/xliff-core-v2.0-os.html). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Xliff.xlf)
**Yaml** | Exports to yaml. | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Yaml.yml)
**YamlDictionary** | Exports to yaml (without plurals and context). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/YamlDictionary.yml)
## Translator
This package includes the following generators:
The class `Gettext\Translator` implements the gettext functions in php. Useful if you don't have the native gettext extension for php or want to avoid problems with it. You can load the translations from a php array file or using a `Gettext\Translations` instance:
```php
use Gettext\Translator;
- `MoGenerator`
- `PoGenerator`
//Create a new instance of the translator
$t = new Translator();
And you can install other formats with loaders and generators:
//Load the translations using any of the following ways:
- [Json](https://github.com/php-gettext/Json)
// 1. from php files (generated by Gettext\Extractors\PhpArray)
$t->loadTranslations('locales/gl.php');
// 2. using the array directly
$array = include 'locales/gl.php';
$t->loadTranslations($array);
## Scanners
// 3. using a Gettext\Translations instance (slower)
$translations = Gettext\Translations::fromPoFile('locales/gl.po');
$t->loadTranslations($translations);
//Now you can use it in your templates
echo $t->gettext('apple');
```
## GettextTranslator
The class `Gettext\GettextTranslator` uses the gettext extension. It's useful because combines the performance of using real gettext functions but with the same API than `Translator` class, so you can switch to one or other translator deppending of the environment without change code of your app.
Scanners allow to search and extract new gettext entries from different sources like php files, twig templates, blade templates, etc. Unlike loaders, scanners allows to extract gettext entries with different domains at the same time:
```php
use Gettext\GettextTranslator;
//Create a new instance
$t = new GettextTranslator();
//It detects the environment variables to set the locale, but you can change it:
$t->setLanguage('gl');
//Load the domains:
$t->loadDomain('messages', 'project/Locale');
//this means you have the file "project/Locale/gl/LC_MESSAGES/messages.po"
//Now you can use it in your templates
echo $t->gettext('apple');
```
## Global functions
use Gettext\Scanner\PhpScanner;
use Gettext\Translations;
To ease the use of translations in your php templates, you can use the provided functions:
//Create a new scanner, adding a translation for each domain we want to get:
$phpScanner = new PhpScanner(
Translations::create('domain1'),
Translations::create('domain2'),
Translations::create('domain3')
);
```php
//Register the translator to use the global functions
$t->register();
//Set a default domain, so any translations with no domain specified, will be added to that domain
$phpScanner->setDefaultDomain('domain1');
echo __('apple'); // it's the same than $t->gettext('apple');
```
//Extract all comments starting with 'i18n:' and 'Translators:'
$phpScanner->extractCommentsStartingWith('i18n:', 'Translators:');
You can scan the php files containing these functions and extract the values with the PhpCode extractor:
//Scan files
foreach (glob('*.php') as $file) {
$phpScanner->scanFile($file);
}
```html
<!-- index.php -->
<html>
<body>
<?= __('Hello world'); ?>
</body>
</html>
//Get the translations
list('domain1' => $domain1, 'domain2' => $domain2, 'domain3' => $domain3) = $phpScanner->getTranslations();
```
This package does not include any scanner by default. But there are some that you can install:
## Merge translations
- [PHP Scanner](https://github.com/php-gettext/PHP-Scanner)
- [JS Scanner](https://github.com/php-gettext/JS-Scanner)
To work with different translations you may want merge them in an unique file. There are two ways to do this:
## Merging translations
The simplest way is adding new translations:
You will want to update or merge translations. The function `mergeWith` create a new `Translations` instance with other translations merged:
```php
use Gettext\Translations;
$translations = Translations::fromPoFile('my-file1.po');
$translations->addFromPoFile('my-file2.po');
$translations3 = $translations1->mergeWith($translations2);
```
A more advanced way is merge two `Translations` instances:
```php
use Gettext\Translations;
//Create a new Translations instances with our translations.
$translations1 = Translations::fromPoFile('my-file1.po');
$translations2 = Translations::fromPoFile('my-file2.po');
//Merge one inside other:
$translations1->mergeWith($translations2);
//Now translations1 has all values
```
The second argument of `mergeWith` defines how the merge will be done. Use the `Gettext\Merge` constants to configure the merging:
But sometimes this is not enough, and this is why we have merging options, allowing to configure how two translations will be merged. These options are defined as constants in the `Gettext\Merge` class, and are the following:
Constant | Description
--------- | -----------
`Merge::ADD` | Adds the translations from `$translations2` that are missing
`Merge::REMOVE` | Removes the translations missing in `$translations2`
`Merge::HEADERS_ADD` | Adds the headers from `$translations2` that are missing
`Merge::HEADERS_REMOVE` | Removes the headers missing in `$translations2`
`Merge::HEADERS_OVERRIDE` | Overrides the headers with the values of `$translations2`
`Merge::LANGUAGE_OVERRIDE` | Set the language defined in `$translations2`
`Merge::DOMAIN_OVERRIDE` | Set the domain defined in `$translations2`
`Merge::TRANSLATIONS_OURS` | Use only the translations present in `$translations1`
`Merge::TRANSLATIONS_THEIRS` | Use only the translations present in `$translations2`
`Merge::TRANSLATION_OVERRIDE` | Override the translation and plural translations with the value of `$translation2`
`Merge::HEADERS_OURS` | Use only the headers of `$translations1`
`Merge::HEADERS_REMOVE` | Use only the headers of `$translations2`
`Merge::HEADERS_OVERRIDE` | Overrides the headers with the values of `$translations2`
`Merge::COMMENTS_OURS` | Use only the comments of `$translation1`
`Merge::COMMENTS_THEIRS` | Use only the comments of `$translation2`
`Merge::EXTRACTED_COMMENTS_OURS` | Use only the extracted comments of `$translation1`
@ -368,58 +213,48 @@ Constant | Description
`Merge::REFERENCES_OURS` | Use only the references of `$translation1`
`Merge::REFERENCES_THEIRS` | Use only the references of `$translation2`
Example:
Use the second argument to configure the merging strategy:
```php
use Gettext\Translations;
use Gettext\Merge;
//Scan the php code to find the latest gettext translations
$phpTranslations = Translations::fromPhpCodeFile('my-templates.php');
//Get the translations of the code that are stored in a po file
$poTranslations = Translations::fromPoFile('locale.po');
$strategy = Merge::TRANSLATIONS_OURS | Merge::HEADERS_OURS;
//Merge the translations from the po file using the references from `$phpTranslations`:
$translations->mergeWith($poTranslations, Merge::REFERENCES_OURS);
//Now save a po file with the result
$translations->toPoFile('locale.po');
$translations3 = $translations1->mergeWith($translations2, $strategy);
```
Note, if the second argument is not defined, the default value is `Merge::DEFAULTS` that's equivalent to `Merge::ADD | Merge::HEADERS_ADD`.
## Use from CLI
There's a Robo task to use this library from the command line interface: https://github.com/oscarotero/GettextRobo
## Use in the browser
If you want to use your translations in the browser, there's a javascript translator: https://github.com/oscarotero/gettext-translator
There are some typical scenarios, one of the most common:
## Third party packages
- Scan php templates searching for entries to translate
- Complete these entries with the translations stored in a .po file
- You may want to add new entries to the .po file
- And also remove those entries present in the .po file but not in the templates (because they were removed)
- But you want to update some translations with new references and extracted comments
- And keep the translations, comments and flags defined in .po file
Twig integration:
For this scenario, you can use the option `Merge::SCAN_AND_LOAD` with the combination of options to fit this needs (SCAN new entries and LOAD a .po file).
* [jaimeperez/twig-configurable-i18n](https://packagist.org/packages/jaimeperez/twig-configurable-i18n)
* [cemerson/translator-twig-extension](https://packagist.org/packages/cemerson/translator-twig-extension)
Framework integration:
```php
$newEntries = $scanner->scanFile('template.php');
$previousEntries = $loader->loadFile('translations.po');
* [Laravel 5](https://packagist.org/packages/eusonlito/laravel-gettext)
* [CakePHP 3](https://packagist.org/packages/k1low/po)
* [Symfony 2](https://packagist.org/packages/mablae/gettext-bundle)
$updatedEntries = $newEntries->mergeWith($previousEntries);
```
[add your package](https://github.com/oscarotero/Gettext/issues/new)
More common scenarios may be added in a future.
## Contributors
Thanks to all [contributors](https://github.com/oscarotero/Gettext/graphs/contributors) specially to [@mlocati](https://github.com/mlocati).
## Donations
---
Please see [CHANGELOG](CHANGELOG.md) for more information about recent changes and [CONTRIBUTING](CONTRIBUTING.md) for contributing details.
If this library is useful for you, consider to donate to the author.
The MIT License (MIT). Please see [LICENSE](LICENSE) for more information.
[Buy me a beer :beer:](https://www.paypal.me/oscarotero)
[ico-version]: https://img.shields.io/packagist/v/gettext/gettext.svg?style=flat-square
[ico-license]: https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square
[ico-ga]: https://github.com/php-gettext/Gettext/workflows/testing/badge.svg
[ico-downloads]: https://img.shields.io/packagist/dt/gettext/gettext.svg?style=flat-square
Thanks in advance!
[link-packagist]: https://packagist.org/packages/gettext/gettext
[link-downloads]: https://packagist.org/packages/gettext/gettext

26
inc/gettext/composer.json

@ -3,7 +3,7 @@
"type": "library",
"description": "PHP gettext manager",
"keywords": ["js", "gettext", "i18n", "translation", "po", "mo"],
"homepage": "https://github.com/oscarotero/Gettext",
"homepage": "https://github.com/php-gettext/Gettext",
"license": "MIT",
"authors": [
{
@ -15,25 +15,18 @@
],
"support": {
"email": "oom@oscarotero.com",
"issues": "https://github.com/oscarotero/Gettext/issues"
"issues": "https://github.com/php-gettext/Gettext/issues"
},
"require": {
"php": ">=5.4.0",
"php": "^7.2|^8.0",
"gettext/languages": "^2.3"
},
"require-dev": {
"illuminate/view": "*",
"twig/twig": "^1.31|^2.0",
"twig/extensions": "*",
"symfony/yaml": "~2",
"phpunit/phpunit": "^4.8|^5.7|^6.5",
"squizlabs/php_codesniffer": "^3.0"
},
"suggest": {
"illuminate/view": "Is necessary if you want to use the Blade extractor",
"twig/twig": "Is necessary if you want to use the Twig extractor",
"twig/extensions": "Is necessary if you want to use the Twig extractor",
"symfony/yaml": "Is necessary if you want to use the Yaml extractor/generator"
"phpunit/phpunit": "^8.0|^9.0",
"squizlabs/php_codesniffer": "^3.0",
"brick/varexporter": "^0.3.5",
"friendsofphp/php-cs-fixer": "^3.2",
"oscarotero/php-cs-fixer-config": "^2.0"
},
"autoload": {
"psr-4": {
@ -49,6 +42,7 @@
"test": [
"phpunit",
"phpcs"
]
],
"cs-fix": "php-cs-fixer fix"
}
}

39
inc/gettext/src/BaseTranslator.php

@ -1,39 +0,0 @@
<?php
namespace Gettext;
abstract class BaseTranslator implements TranslatorInterface
{
/** @var TranslatorInterface */
public static $current;
/**
* @see TranslatorInterface
*/
public function noop($original)
{
return $original;
}
/**
* @see TranslatorInterface
*/
public function register()
{
$previous = static::$current;
static::$current = $this;
static::includeFunctions();
return $previous;
}
/**
* Include the gettext functions
*/
public static function includeFunctions()
{
include_once __DIR__.'/translator_functions.php';
}
}

89
inc/gettext/src/Comments.php

@ -0,0 +1,89 @@
<?php
declare(strict_types = 1);
namespace Gettext;
use ArrayIterator;
use Countable;
use IteratorAggregate;
use JsonSerializable;
use ReturnTypeWillChange;
/**
* Class to manage the comments of a translation.
*/
class Comments implements JsonSerializable, Countable, IteratorAggregate
{
protected $comments = [];
public static function __set_state(array $state): Comments
{
return new static(...$state['comments']);
}
public function __construct(string ...$comments)
{
if (!empty($comments)) {
$this->add(...$comments);
}
}
public function __debugInfo()
{
return $this->toArray();
}
public function add(string ...$comments): self
{
foreach ($comments as $comment) {
if (!in_array($comment, $this->comments)) {
$this->comments[] = $comment;
}
}
return $this;
}
public function delete(string ...$comments): self
{
foreach ($comments as $comment) {
$key = array_search($comment, $this->comments);
if (is_int($key)) {
array_splice($this->comments, $key, 1);
}
}
return $this;
}
#[ReturnTypeWillChange]
public function jsonSerialize()
{
return $this->toArray();
}
#[ReturnTypeWillChange]
public function getIterator()
{
return new ArrayIterator($this->comments);
}
public function count(): int
{
return count($this->comments);
}
public function toArray(): array
{
return $this->comments;
}
public function mergeWith(Comments $comments): Comments
{
$merged = clone $this;
$merged->add(...$comments->comments);
return $merged;
}
}

29
inc/gettext/src/Extractors/Blade.php

@ -1,29 +0,0 @@
<?php
namespace Gettext\Extractors;
use Gettext\Translations;
use Illuminate\Filesystem\Filesystem;
use Illuminate\View\Compilers\BladeCompiler;
/**
* Class to get gettext strings from blade.php files returning arrays.
*/
class Blade extends Extractor implements ExtractorInterface
{
/**
* {@inheritdoc}
*/
public static function fromString($string, Translations $translations, array $options = [])
{
if (empty($options['facade'])) {
$cachePath = empty($options['cachePath']) ? sys_get_temp_dir() : $options['cachePath'];
$bladeCompiler = new BladeCompiler(new Filesystem(), $cachePath);
$string = $bladeCompiler->compileString($string);
} else {
$string = $options['facade']::compileString($string);
}
PhpCode::fromString($string, $translations, $options);
}
}

53
inc/gettext/src/Extractors/Csv.php

@ -1,53 +0,0 @@
<?php
namespace Gettext\Extractors;
use Gettext\Translations;
use Gettext\Utils\HeadersExtractorTrait;
use Gettext\Utils\CsvTrait;
/**
* Class to get gettext strings from csv.
*/
class Csv extends Extractor implements ExtractorInterface
{
use HeadersExtractorTrait;
use CsvTrait;
public static $options = [
'delimiter' => ",",
'enclosure' => '"',
'escape_char' => "\\"
];
/**
* {@inheritdoc}
*/
public static function fromString($string, Translations $translations, array $options = [])
{
$options += static::$options;
$handle = fopen('php://memory', 'w');
fputs($handle, $string);
rewind($handle);
while ($row = static::fgetcsv($handle, $options)) {
$context = array_shift($row);
$original = array_shift($row);
if ($context === '' && $original === '') {
static::extractHeaders(array_shift($row), $translations);
continue;
}
$translation = $translations->insert($context, $original);
if (!empty($row)) {
$translation->setTranslation(array_shift($row));
$translation->setPluralTranslations($row);
}
}
fclose($handle);
}
}

47
inc/gettext/src/Extractors/CsvDictionary.php

@ -1,47 +0,0 @@
<?php
namespace Gettext\Extractors;
use Gettext\Translations;
use Gettext\Utils\HeadersExtractorTrait;
use Gettext\Utils\CsvTrait;
/**
* Class to get gettext strings from csv.
*/
class CsvDictionary extends Extractor implements ExtractorInterface
{
use HeadersExtractorTrait;
use CsvTrait;
public static $options = [
'delimiter' => ",",
'enclosure' => '"',
'escape_char' => "\\"
];
/**
* {@inheritdoc}
*/
public static function fromString($string, Translations $translations, array $options = [])
{
$options += static::$options;
$handle = fopen('php://memory', 'w');
fputs($handle, $string);
rewind($handle);
while ($row = static::fgetcsv($handle, $options)) {
list($original, $translation) = $row + ['', ''];
if ($original === '') {
static::extractHeaders($translation, $translations);
continue;
}
$translations->insert(null, $original)->setTranslation($translation);
}
fclose($handle);
}
}

80
inc/gettext/src/Extractors/Extractor.php

@ -1,80 +0,0 @@
<?php
namespace Gettext\Extractors;
use Exception;
use InvalidArgumentException;
use Gettext\Translations;
abstract class Extractor implements ExtractorInterface
{
/**
* {@inheritdoc}
*/
public static function fromFile($file, Translations $translations, array $options = [])
{
foreach (static::getFiles($file) as $file) {
$options['file'] = $file;
static::fromString(static::readFile($file), $translations, $options);
}
}
/**
* Checks and returns all files.
*
* @param string|array $file The file/s
*
* @return array The file paths
*/
protected static function getFiles($file)
{
if (empty($file)) {
throw new InvalidArgumentException('There is not any file defined');
}
if (is_string($file)) {
if (!is_file($file)) {
throw new InvalidArgumentException("'$file' is not a valid file");
}
if (!is_readable($file)) {
throw new InvalidArgumentException("'$file' is not a readable file");
}
return [$file];
}
if (is_array($file)) {
$files = [];
foreach ($file as $f) {
$files = array_merge($files, static::getFiles($f));
}
return $files;
}
throw new InvalidArgumentException('The first argument must be string or array');
}
/**
* Reads and returns the content of a file.
*
* @param string $file
*
* @return string
*/
protected static function readFile($file)
{
$length = filesize($file);
if (!($fd = fopen($file, 'rb'))) {
throw new Exception("Cannot read the file '$file', probably permissions");
}
$content = $length ? fread($fd, $length) : '';
fclose($fd);
return $content;
}
}

26
inc/gettext/src/Extractors/ExtractorInterface.php

@ -1,26 +0,0 @@
<?php
namespace Gettext\Extractors;
use Gettext\Translations;
interface ExtractorInterface
{
/**
* Extract the translations from a file.
*
* @param array|string $file A path of a file or files
* @param Translations $translations The translations instance to append the new translations.
* @param array $options
*/
public static function fromFile($file, Translations $translations, array $options = []);
/**
* Parses a string and append the translations found in the Translations instance.
*
* @param string $string
* @param Translations $translations
* @param array $options
*/
public static function fromString($string, Translations $translations, array $options = []);
}

28
inc/gettext/src/Extractors/ExtractorMultiInterface.php

@ -1,28 +0,0 @@
<?php
namespace Gettext\Extractors;
use Gettext\Translations;
interface ExtractorMultiInterface
{
/**
* Parses a string and append the translations found in the Translations instance.
* Allows scanning for multiple domains at a time (each Translation has to have a different domain)
*
* @param string $string
* @param Translations[] $translations
* @param array $options
*/
public static function fromStringMultiple($string, array $translations, array $options = []);
/**
* Parses a string and append the translations found in the Translations instance.
* Allows scanning for multiple domains at a time (each Translation has to have a different domain)
*
* @param $file
* @param Translations[] $translations
* @param array $options
*/
public static function fromFileMultiple($file, array $translations, array $options = []);
}

55
inc/gettext/src/Extractors/Jed.php

@ -1,55 +0,0 @@
<?php
namespace Gettext\Extractors;
use Gettext\Translations;
/**
* Class to get gettext strings from json files.
*/
class Jed extends Extractor implements ExtractorInterface
{
/**
* {@inheritdoc}
*/
public static function fromString($string, Translations $translations, array $options = [])
{
static::extract(json_decode($string, true), $translations);
}
/**
* Handle an array of translations and append to the Translations instance.
*
* @param array $content
* @param Translations $translations
*/
public static function extract(array $content, Translations $translations)
{
$messages = current($content);
$headers = isset($messages['']) ? $messages[''] : null;
unset($messages['']);
if (!empty($headers['domain'])) {
$translations->setDomain($headers['domain']);
}
if (!empty($headers['lang'])) {
$translations->setLanguage($headers['lang']);
}
if (!empty($headers['plural-forms'])) {
$translations->setHeader(Translations::HEADER_PLURAL, $headers['plural-forms']);
}
$context_glue = '\u0004';
foreach ($messages as $key => $translation) {
$key = explode($context_glue, $key);
$context = isset($key[1]) ? array_shift($key) : '';
$translations->insert($context, array_shift($key))
->setTranslation(array_shift($translation))
->setPluralTranslations($translation);
}
}
}

74
inc/gettext/src/Extractors/JsCode.php

@ -1,74 +0,0 @@
<?php
namespace Gettext\Extractors;
use Exception;
use Gettext\Translations;
use Gettext\Utils\FunctionsScanner;
/**
* Class to get gettext strings from javascript files.
*/
class JsCode extends Extractor implements ExtractorInterface, ExtractorMultiInterface
{
public static $options = [
'constants' => [],
'functions' => [
'gettext' => 'gettext',
'__' => 'gettext',
'ngettext' => 'ngettext',
'n__' => 'ngettext',
'pgettext' => 'pgettext',
'p__' => 'pgettext',
'dgettext' => 'dgettext',
'd__' => 'dgettext',
'dngettext' => 'dngettext',
'dn__' => 'dngettext',
'dpgettext' => 'dpgettext',
'dp__' => 'dpgettext',
'npgettext' => 'npgettext',
'np__' => 'npgettext',
'dnpgettext' => 'dnpgettext',
'dnp__' => 'dnpgettext',
'noop' => 'noop',
'noop__' => 'noop',
],
];
protected static $functionsScannerClass = 'Gettext\Utils\JsFunctionsScanner';
/**
* @inheritdoc
* @throws Exception
*/
public static function fromString($string, Translations $translations, array $options = [])
{
static::fromStringMultiple($string, [$translations], $options);
}
/**
* @inheritDoc
* @throws Exception
*/
public static function fromStringMultiple($string, array $translations, array $options = [])
{
$options += static::$options;
/** @var FunctionsScanner $functions */
$functions = new static::$functionsScannerClass($string);
$functions->saveGettextFunctions($translations, $options);
}
/**
* @inheritDoc
* @throws Exception
*/
public static function fromFileMultiple($file, array $translations, array $options = [])
{
foreach (static::getFiles($file) as $file) {
$options['file'] = $file;
static::fromStringMultiple(static::readFile($file), $translations, $options);
}
}
}

26
inc/gettext/src/Extractors/Json.php

@ -1,26 +0,0 @@
<?php
namespace Gettext\Extractors;
use Gettext\Translations;
use Gettext\Utils\MultidimensionalArrayTrait;
/**
* Class to get gettext strings from json.
*/
class Json extends Extractor implements ExtractorInterface
{
use MultidimensionalArrayTrait;
/**
* {@inheritdoc}
*/
public static function fromString($string, Translations $translations, array $options = [])
{
$messages = json_decode($string, true);
if (is_array($messages)) {
static::fromArray($messages, $translations);
}
}
}

26
inc/gettext/src/Extractors/JsonDictionary.php

@ -1,26 +0,0 @@
<?php
namespace Gettext\Extractors;
use Gettext\Translations;
use Gettext\Utils\DictionaryTrait;
/**
* Class to get gettext strings from plain json.
*/
class JsonDictionary extends Extractor implements ExtractorInterface
{
use DictionaryTrait;
/**
* {@inheritdoc}
*/
public static function fromString($string, Translations $translations, array $options = [])
{
$messages = json_decode($string, true);
if (is_array($messages)) {
static::fromArray($messages, $translations);
}
}
}

131
inc/gettext/src/Extractors/Mo.php

@ -1,131 +0,0 @@
<?php
namespace Gettext\Extractors;
use Exception;
use Gettext\Translations;
use Gettext\Utils\StringReader;
/**
* Class to get gettext strings from .mo files.
*/
class Mo extends Extractor implements ExtractorInterface
{
const MAGIC1 = -1794895138;
const MAGIC2 = -569244523;
const MAGIC3 = 2500072158;
protected static $stringReaderClass = 'Gettext\Utils\StringReader';
/**
* {@inheritdoc}
*/
public static function fromString($string, Translations $translations, array $options = [])
{
/** @var StringReader $stream */
$stream = new static::$stringReaderClass($string);
$magic = static::readInt($stream, 'V');
if (($magic === static::MAGIC1) || ($magic === static::MAGIC3)) { //to make sure it works for 64-bit platforms
$byteOrder = 'V'; //low endian
} elseif ($magic === (static::MAGIC2 & 0xFFFFFFFF)) {
$byteOrder = 'N'; //big endian
} else {
throw new Exception('Not MO file');
}
static::readInt($stream, $byteOrder);
$total = static::readInt($stream, $byteOrder); //total string count
$originals = static::readInt($stream, $byteOrder); //offset of original table
$tran = static::readInt($stream, $byteOrder); //offset of translation table
$stream->seekto($originals);
$table_originals = static::readIntArray($stream, $byteOrder, $total * 2);
$stream->seekto($tran);
$table_translations = static::readIntArray($stream, $byteOrder, $total * 2);
for ($i = 0; $i < $total; ++$i) {
$next = $i * 2;
$stream->seekto($table_originals[$next + 2]);
$original = $stream->read($table_originals[$next + 1]);
$stream->seekto($table_translations[$next + 2]);