commit vendor

This commit is contained in:
2025-11-11 14:49:30 +01:00
parent f33121a308
commit 6d03080c00
2436 changed files with 483781 additions and 0 deletions

View File

@ -0,0 +1,81 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator\Loader;
/**
* Abstract file loader implementation; provides facilities around resolving
* files via the include_path.
*/
abstract class AbstractFileLoader implements FileLoaderInterface
{
/**
* Whether or not to consult the include_path when locating files
*
* @var bool
*/
protected $useIncludePath = false;
/**
* Indicate whether or not to use the include_path to resolve translation files
*
* @param bool $flag
* @return self
*/
public function setUseIncludePath($flag = true)
{
$this->useIncludePath = (bool) $flag;
return $this;
}
/**
* Are we using the include_path to resolve translation files?
*
* @return bool
*/
public function useIncludePath()
{
return $this->useIncludePath;
}
/**
* Resolve a translation file
*
* Checks if the file exists and is readable, returning a boolean false if not; if the "useIncludePath"
* flag is enabled, it will attempt to resolve the file from the
* include_path if the file does not exist on the current working path.
*
* @param string $filename
* @return string|false
*/
protected function resolveFile($filename)
{
if (! is_file($filename) || ! is_readable($filename)) {
if (! $this->useIncludePath()) {
return false;
}
return $this->resolveViaIncludePath($filename);
}
return $filename;
}
/**
* Resolve a translation file via the include_path
*
* @param string $filename
* @return string|false
*/
protected function resolveViaIncludePath($filename)
{
$resolvedIncludePath = stream_resolve_include_path($filename);
if (! $resolvedIncludePath || ! is_file($resolvedIncludePath) || ! is_readable($resolvedIncludePath)) {
return false;
}
return $resolvedIncludePath;
}
}

View File

@ -0,0 +1,26 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator\Loader;
use Laminas\I18n\Translator\TextDomain;
/**
* File loader interface.
*/
interface FileLoaderInterface
{
/**
* Load translations from a file.
*
* @param string $locale
* @param string $filename
* @return TextDomain|null
*/
public function load($locale, $filename);
}

View File

@ -0,0 +1,190 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator\Loader;
use Laminas\I18n\Exception;
use Laminas\I18n\Translator\Plural\Rule as PluralRule;
use Laminas\I18n\Translator\TextDomain;
use Laminas\Stdlib\ErrorHandler;
/**
* Gettext loader.
*/
class Gettext extends AbstractFileLoader
{
/**
* Current file pointer.
*
* @var resource
*/
protected $file;
/**
* Whether the current file is little endian.
*
* @var bool
*/
protected $littleEndian;
/**
* load(): defined by FileLoaderInterface.
*
* @see FileLoaderInterface::load()
* @param string $locale
* @param string $filename
* @return TextDomain
* @throws Exception\InvalidArgumentException
*/
public function load($locale, $filename)
{
$resolvedFile = $this->resolveFile($filename);
if (! $resolvedFile) {
throw new Exception\InvalidArgumentException(sprintf(
'Could not find or open file %s for reading',
$filename
));
}
$textDomain = new TextDomain();
ErrorHandler::start();
$this->file = fopen($resolvedFile, 'rb');
$error = ErrorHandler::stop();
if (false === $this->file) {
throw new Exception\InvalidArgumentException(sprintf(
'Could not open file %s for reading',
$filename
), 0, $error);
}
// Verify magic number
$magic = fread($this->file, 4);
if ($magic === "\x95\x04\x12\xde") {
$this->littleEndian = false;
} elseif ($magic === "\xde\x12\x04\x95") {
$this->littleEndian = true;
} else {
fclose($this->file);
throw new Exception\InvalidArgumentException(sprintf(
'%s is not a valid gettext file',
$filename
));
}
// Verify major revision (only 0 and 1 supported)
$majorRevision = ($this->readInteger() >> 16);
if ($majorRevision !== 0 && $majorRevision !== 1) {
fclose($this->file);
throw new Exception\InvalidArgumentException(sprintf(
'%s has an unknown major revision',
$filename
));
}
// Gather main information
$numStrings = $this->readInteger();
$originalStringTableOffset = $this->readInteger();
$translationStringTableOffset = $this->readInteger();
// Usually there follow size and offset of the hash table, but we have
// no need for it, so we skip them.
fseek($this->file, $originalStringTableOffset);
$originalStringTable = $this->readIntegerList(2 * $numStrings);
fseek($this->file, $translationStringTableOffset);
$translationStringTable = $this->readIntegerList(2 * $numStrings);
// Read in all translations
for ($current = 0; $current < $numStrings; $current++) {
$sizeKey = $current * 2 + 1;
$offsetKey = $current * 2 + 2;
$originalStringSize = $originalStringTable[$sizeKey];
$originalStringOffset = $originalStringTable[$offsetKey];
$translationStringSize = $translationStringTable[$sizeKey];
$translationStringOffset = $translationStringTable[$offsetKey];
$originalString = [''];
if ($originalStringSize > 0) {
fseek($this->file, $originalStringOffset);
$originalString = explode("\0", fread($this->file, $originalStringSize));
}
if ($translationStringSize > 0) {
fseek($this->file, $translationStringOffset);
$translationString = explode("\0", fread($this->file, $translationStringSize));
if (isset($originalString[1], $translationString[1])) {
$textDomain[$originalString[0]] = $translationString;
array_shift($originalString);
foreach ($originalString as $string) {
if (! isset($textDomain[$string])) {
$textDomain[$string] = '';
}
}
} else {
$textDomain[$originalString[0]] = $translationString[0];
}
}
}
// Read header entries
if ($textDomain->offsetExists('')) {
$rawHeaders = explode("\n", trim($textDomain['']));
foreach ($rawHeaders as $rawHeader) {
list($header, $content) = explode(':', $rawHeader, 2);
if (strtolower(trim($header)) === 'plural-forms') {
$textDomain->setPluralRule(PluralRule::fromString($content));
}
}
unset($textDomain['']);
}
fclose($this->file);
return $textDomain;
}
/**
* Read a single integer from the current file.
*
* @return int
*/
protected function readInteger()
{
if ($this->littleEndian) {
$result = unpack('Vint', fread($this->file, 4));
} else {
$result = unpack('Nint', fread($this->file, 4));
}
return $result['int'];
}
/**
* Read an integer from the current file.
*
* @param int $num
* @return int
*/
protected function readIntegerList($num)
{
if ($this->littleEndian) {
return unpack('V' . $num, fread($this->file, 4 * $num));
}
return unpack('N' . $num, fread($this->file, 4 * $num));
}
}

View File

@ -0,0 +1,80 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator\Loader;
use Laminas\Config\Reader\Ini as IniReader;
use Laminas\I18n\Exception;
use Laminas\I18n\Translator\Plural\Rule as PluralRule;
use Laminas\I18n\Translator\TextDomain;
/**
* PHP INI format loader.
*/
class Ini extends AbstractFileLoader
{
/**
* load(): defined by FileLoaderInterface.
*
* @see FileLoaderInterface::load()
* @param string $locale
* @param string $filename
* @return TextDomain
* @throws Exception\InvalidArgumentException
*/
public function load($locale, $filename)
{
$resolvedIncludePath = stream_resolve_include_path($filename);
$fromIncludePath = ($resolvedIncludePath !== false) ? $resolvedIncludePath : $filename;
if (! $fromIncludePath || ! is_file($fromIncludePath) || ! is_readable($fromIncludePath)) {
throw new Exception\InvalidArgumentException(sprintf(
'Could not find or open file %s for reading',
$filename
));
}
$messages = [];
$iniReader = new IniReader();
$messagesNamespaced = $iniReader->fromFile($fromIncludePath);
$list = $messagesNamespaced;
if (isset($messagesNamespaced['translation'])) {
$list = $messagesNamespaced['translation'];
}
foreach ($list as $message) {
if (! is_array($message) || count($message) < 2) {
throw new Exception\InvalidArgumentException(
'Each INI row must be an array with message and translation'
);
}
if (isset($message['message'], $message['translation'])) {
$messages[$message['message']] = $message['translation'];
continue;
}
$messages[array_shift($message)] = array_shift($message);
}
if (! is_array($messages)) {
throw new Exception\InvalidArgumentException(sprintf(
'Expected an array, but received %s',
gettype($messages)
));
}
$textDomain = new TextDomain($messages);
if (isset($messagesNamespaced['plural']['plural_forms'])) {
$textDomain->setPluralRule(
PluralRule::fromString($messagesNamespaced['plural']['plural_forms'])
);
}
return $textDomain;
}
}

View File

@ -0,0 +1,63 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator\Loader;
use Laminas\I18n\Exception;
use Laminas\I18n\Translator\Plural\Rule as PluralRule;
use Laminas\I18n\Translator\TextDomain;
/**
* PHP array loader.
*/
class PhpArray extends AbstractFileLoader
{
/**
* load(): defined by FileLoaderInterface.
*
* @see FileLoaderInterface::load()
* @param string $locale
* @param string $filename
* @return TextDomain
* @throws Exception\InvalidArgumentException
*/
public function load($locale, $filename)
{
$resolvedIncludePath = stream_resolve_include_path($filename);
$fromIncludePath = ($resolvedIncludePath !== false) ? $resolvedIncludePath : $filename;
if (! $fromIncludePath || ! is_file($fromIncludePath) || ! is_readable($fromIncludePath)) {
throw new Exception\InvalidArgumentException(sprintf(
'Could not find or open file %s for reading',
$filename
));
}
$messages = include $fromIncludePath;
if (! is_array($messages)) {
throw new Exception\InvalidArgumentException(sprintf(
'Expected an array, but received %s',
gettype($messages)
));
}
$textDomain = new TextDomain($messages);
if ($textDomain->offsetExists('')) {
if (isset($textDomain['']['plural_forms'])) {
$textDomain->setPluralRule(
PluralRule::fromString($textDomain['']['plural_forms'])
);
}
unset($textDomain['']);
}
return $textDomain;
}
}

View File

@ -0,0 +1,72 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator\Loader;
use Laminas\I18n\Exception;
use Laminas\I18n\Translator\Plural\Rule as PluralRule;
use Laminas\I18n\Translator\TextDomain;
/**
* PHP Memory array loader.
*/
class PhpMemoryArray implements RemoteLoaderInterface
{
/**
* @var array
*/
protected $messages;
public function __construct($messages)
{
$this->messages = $messages;
}
/**
* Load translations from a remote source.
*
* @param string $locale
* @param string $textDomain
* @return TextDomain
* @throws Exception\InvalidArgumentException
*/
public function load($locale, $textDomain)
{
if (! is_array($this->messages)) {
throw new Exception\InvalidArgumentException(
sprintf('Expected an array, but received %s', gettype($this->messages))
);
}
if (! isset($this->messages[$textDomain])) {
throw new Exception\InvalidArgumentException(
sprintf('Expected textdomain "%s" to be an array, but it is not set', $textDomain)
);
}
if (! isset($this->messages[$textDomain][$locale])) {
throw new Exception\InvalidArgumentException(
sprintf('Expected locale "%s" to be an array, but it is not set', $locale)
);
}
$textDomain = new TextDomain($this->messages[$textDomain][$locale]);
if ($textDomain->offsetExists('')) {
if (isset($textDomain['']['plural_forms'])) {
$textDomain->setPluralRule(
PluralRule::fromString($textDomain['']['plural_forms'])
);
}
unset($textDomain['']);
}
return $textDomain;
}
}

View File

@ -0,0 +1,26 @@
<?php
/**
* @see https://github.com/laminas/laminas-i18n for the canonical source repository
* @copyright https://github.com/laminas/laminas-i18n/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-i18n/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\I18n\Translator\Loader;
use Laminas\I18n\Translator\TextDomain;
/**
* Remote loader interface.
*/
interface RemoteLoaderInterface
{
/**
* Load translations from a remote source.
*
* @param string $locale
* @param string $textDomain
* @return TextDomain|null
*/
public function load($locale, $textDomain);
}