git subrepo commit (merge) mailcow/src/mailcow-dockerized
subrepo: subdir: "mailcow/src/mailcow-dockerized"
merged: "02ae5285"
upstream: origin: "https://github.com/mailcow/mailcow-dockerized.git"
branch: "master"
commit: "649a5c01"
git-subrepo: version: "0.4.3"
origin: "???"
commit: "???"
Change-Id: I870ad468fba026cc5abf3c5699ed1e12ff28b32b
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/CHANGELOG.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/CHANGELOG.md
new file mode 100644
index 0000000..3341328
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/CHANGELOG.md
@@ -0,0 +1,169 @@
+CHANGELOG
+=========
+
+5.3
+---
+
+ * Add `translation:pull` and `translation:push` commands to manage translations with third-party providers
+ * Add `TranslatorBagInterface::getCatalogues` method
+ * Add support to load XLIFF string in `XliffFileLoader`
+
+5.2.0
+-----
+
+ * added support for calling `trans` with ICU formatted messages
+ * added `PseudoLocalizationTranslator`
+ * added `TranslatableMessage` objects that represent a message that can be translated
+ * added the `t()` function to easily create `TranslatableMessage` objects
+ * Added support for extracting messages from `TranslatableMessage` objects
+
+5.1.0
+-----
+
+ * added support for `name` attribute on `unit` element from xliff2 to be used as a translation key instead of always the `source` element
+
+5.0.0
+-----
+
+ * removed support for using `null` as the locale in `Translator`
+ * removed `TranslatorInterface`
+ * removed `MessageSelector`
+ * removed `ChoiceMessageFormatterInterface`
+ * removed `PluralizationRule`
+ * removed `Interval`
+ * removed `transChoice()` methods, use the trans() method instead with a %count% parameter
+ * removed `FileDumper::setBackup()` and `TranslationWriter::disableBackup()`
+ * removed `MessageFormatter::choiceFormat()`
+ * added argument `$filename` to `PhpExtractor::parseTokens()`
+ * removed support for implicit STDIN usage in the `lint:xliff` command, use `lint:xliff -` (append a dash) instead to make it explicit.
+
+4.4.0
+-----
+
+ * deprecated support for using `null` as the locale in `Translator`
+ * deprecated accepting STDIN implicitly when using the `lint:xliff` command, use `lint:xliff -` (append a dash) instead to make it explicit.
+ * Marked the `TranslationDataCollector` class as `@final`.
+
+4.3.0
+-----
+
+ * Improved Xliff 1.2 loader to load the original file's metadata
+ * Added `TranslatorPathsPass`
+
+4.2.0
+-----
+
+ * Started using ICU parent locales as fallback locales.
+ * allow using the ICU message format using domains with the "+intl-icu" suffix
+ * deprecated `Translator::transChoice()` in favor of using `Translator::trans()` with a `%count%` parameter
+ * deprecated `TranslatorInterface` in favor of `Symfony\Contracts\Translation\TranslatorInterface`
+ * deprecated `MessageSelector`, `Interval` and `PluralizationRules`; use `IdentityTranslator` instead
+ * Added `IntlFormatter` and `IntlFormatterInterface`
+ * added support for multiple files and directories in `XliffLintCommand`
+ * Marked `Translator::getFallbackLocales()` and `TranslationDataCollector::getFallbackLocales()` as internal
+
+4.1.0
+-----
+
+ * The `FileDumper::setBackup()` method is deprecated.
+ * The `TranslationWriter::disableBackup()` method is deprecated.
+ * The `XliffFileDumper` will write "name" on the "unit" node when dumping XLIFF 2.0.
+
+4.0.0
+-----
+
+ * removed the backup feature of the `FileDumper` class
+ * removed `TranslationWriter::writeTranslations()` method
+ * removed support for passing `MessageSelector` instances to the constructor of the `Translator` class
+
+3.4.0
+-----
+
+ * Added `TranslationDumperPass`
+ * Added `TranslationExtractorPass`
+ * Added `TranslatorPass`
+ * Added `TranslationReader` and `TranslationReaderInterface`
+ * Added `<notes>` section to the Xliff 2.0 dumper.
+ * Improved Xliff 2.0 loader to load `<notes>` section.
+ * Added `TranslationWriterInterface`
+ * Deprecated `TranslationWriter::writeTranslations` in favor of `TranslationWriter::write`
+ * added support for adding custom message formatter and decoupling the default one.
+ * Added `PhpExtractor`
+ * Added `PhpStringTokenParser`
+
+3.2.0
+-----
+
+ * Added support for escaping `|` in plural translations with double pipe.
+
+3.1.0
+-----
+
+ * Deprecated the backup feature of the file dumper classes.
+
+3.0.0
+-----
+
+ * removed `FileDumper::format()` method.
+ * Changed the visibility of the locale property in `Translator` from protected to private.
+
+2.8.0
+-----
+
+ * deprecated FileDumper::format(), overwrite FileDumper::formatCatalogue() instead.
+ * deprecated Translator::getMessages(), rely on TranslatorBagInterface::getCatalogue() instead.
+ * added `FileDumper::formatCatalogue` which allows format the catalogue without dumping it into file.
+ * added option `json_encoding` to JsonFileDumper
+ * added options `as_tree`, `inline` to YamlFileDumper
+ * added support for XLIFF 2.0.
+ * added support for XLIFF target and tool attributes.
+ * added message parameters to DataCollectorTranslator.
+ * [DEPRECATION] The `DiffOperation` class has been deprecated and
+ will be removed in Symfony 3.0, since its operation has nothing to do with 'diff',
+ so the class name is misleading. The `TargetOperation` class should be used for
+ this use-case instead.
+
+2.7.0
+-----
+
+ * added DataCollectorTranslator for collecting the translated messages.
+
+2.6.0
+-----
+
+ * added possibility to cache catalogues
+ * added TranslatorBagInterface
+ * added LoggingTranslator
+ * added Translator::getMessages() for retrieving the message catalogue as an array
+
+2.5.0
+-----
+
+ * added relative file path template to the file dumpers
+ * added optional backup to the file dumpers
+ * changed IcuResFileDumper to extend FileDumper
+
+2.3.0
+-----
+
+ * added classes to make operations on catalogues (like making a diff or a merge on 2 catalogues)
+ * added Translator::getFallbackLocales()
+ * deprecated Translator::setFallbackLocale() in favor of the new Translator::setFallbackLocales() method
+
+2.2.0
+-----
+
+ * QtTranslationsLoader class renamed to QtFileLoader. QtTranslationsLoader is deprecated and will be removed in 2.3.
+ * [BC BREAK] uniformized the exception thrown by the load() method when an error occurs. The load() method now
+ throws Symfony\Component\Translation\Exception\NotFoundResourceException when a resource cannot be found
+ and Symfony\Component\Translation\Exception\InvalidResourceException when a resource is invalid.
+ * changed the exception class thrown by some load() methods from \RuntimeException to \InvalidArgumentException
+ (IcuDatFileLoader, IcuResFileLoader and QtFileLoader)
+
+2.1.0
+-----
+
+ * added support for more than one fallback locale
+ * added support for extracting translation messages from templates (Twig and PHP)
+ * added dumpers for translation catalogs
+ * added support for QT, gettext, and ResourceBundles
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Catalogue/AbstractOperation.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Catalogue/AbstractOperation.php
new file mode 100644
index 0000000..9869fbb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Catalogue/AbstractOperation.php
@@ -0,0 +1,192 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Catalogue;
+
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\Exception\LogicException;
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\MessageCatalogueInterface;
+
+/**
+ * Base catalogues binary operation class.
+ *
+ * A catalogue binary operation performs operation on
+ * source (the left argument) and target (the right argument) catalogues.
+ *
+ * @author Jean-François Simon <contact@jfsimon.fr>
+ */
+abstract class AbstractOperation implements OperationInterface
+{
+ public const OBSOLETE_BATCH = 'obsolete';
+ public const NEW_BATCH = 'new';
+ public const ALL_BATCH = 'all';
+
+ protected $source;
+ protected $target;
+ protected $result;
+
+ /**
+ * @var array|null The domains affected by this operation
+ */
+ private $domains;
+
+ /**
+ * This array stores 'all', 'new' and 'obsolete' messages for all valid domains.
+ *
+ * The data structure of this array is as follows:
+ *
+ * [
+ * 'domain 1' => [
+ * 'all' => [...],
+ * 'new' => [...],
+ * 'obsolete' => [...]
+ * ],
+ * 'domain 2' => [
+ * 'all' => [...],
+ * 'new' => [...],
+ * 'obsolete' => [...]
+ * ],
+ * ...
+ * ]
+ *
+ * @var array The array that stores 'all', 'new' and 'obsolete' messages
+ */
+ protected $messages;
+
+ /**
+ * @throws LogicException
+ */
+ public function __construct(MessageCatalogueInterface $source, MessageCatalogueInterface $target)
+ {
+ if ($source->getLocale() !== $target->getLocale()) {
+ throw new LogicException('Operated catalogues must belong to the same locale.');
+ }
+
+ $this->source = $source;
+ $this->target = $target;
+ $this->result = new MessageCatalogue($source->getLocale());
+ $this->messages = [];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDomains()
+ {
+ if (null === $this->domains) {
+ $this->domains = array_values(array_unique(array_merge($this->source->getDomains(), $this->target->getDomains())));
+ }
+
+ return $this->domains;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMessages(string $domain)
+ {
+ if (!\in_array($domain, $this->getDomains())) {
+ throw new InvalidArgumentException(sprintf('Invalid domain: "%s".', $domain));
+ }
+
+ if (!isset($this->messages[$domain][self::ALL_BATCH])) {
+ $this->processDomain($domain);
+ }
+
+ return $this->messages[$domain][self::ALL_BATCH];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getNewMessages(string $domain)
+ {
+ if (!\in_array($domain, $this->getDomains())) {
+ throw new InvalidArgumentException(sprintf('Invalid domain: "%s".', $domain));
+ }
+
+ if (!isset($this->messages[$domain][self::NEW_BATCH])) {
+ $this->processDomain($domain);
+ }
+
+ return $this->messages[$domain][self::NEW_BATCH];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getObsoleteMessages(string $domain)
+ {
+ if (!\in_array($domain, $this->getDomains())) {
+ throw new InvalidArgumentException(sprintf('Invalid domain: "%s".', $domain));
+ }
+
+ if (!isset($this->messages[$domain][self::OBSOLETE_BATCH])) {
+ $this->processDomain($domain);
+ }
+
+ return $this->messages[$domain][self::OBSOLETE_BATCH];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getResult()
+ {
+ foreach ($this->getDomains() as $domain) {
+ if (!isset($this->messages[$domain])) {
+ $this->processDomain($domain);
+ }
+ }
+
+ return $this->result;
+ }
+
+ /**
+ * @param self::*_BATCH $batch
+ */
+ public function moveMessagesToIntlDomainsIfPossible(string $batch = self::ALL_BATCH): void
+ {
+ // If MessageFormatter class does not exists, intl domains are not supported.
+ if (!class_exists(\MessageFormatter::class)) {
+ return;
+ }
+
+ foreach ($this->getDomains() as $domain) {
+ $intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;
+ switch ($batch) {
+ case self::OBSOLETE_BATCH: $messages = $this->getObsoleteMessages($domain); break;
+ case self::NEW_BATCH: $messages = $this->getNewMessages($domain); break;
+ case self::ALL_BATCH: $messages = $this->getMessages($domain); break;
+ default: throw new \InvalidArgumentException(sprintf('$batch argument must be one of ["%s", "%s", "%s"].', self::ALL_BATCH, self::NEW_BATCH, self::OBSOLETE_BATCH));
+ }
+
+ if (!$messages || (!$this->source->all($intlDomain) && $this->source->all($domain))) {
+ continue;
+ }
+
+ $result = $this->getResult();
+ $allIntlMessages = $result->all($intlDomain);
+ $currentMessages = array_diff_key($messages, $result->all($domain));
+ $result->replace($currentMessages, $domain);
+ $result->replace($allIntlMessages + $messages, $intlDomain);
+ }
+ }
+
+ /**
+ * Performs operation on source and target catalogues for the given domain and
+ * stores the results.
+ *
+ * @param string $domain The domain which the operation will be performed for
+ */
+ abstract protected function processDomain(string $domain);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Catalogue/MergeOperation.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Catalogue/MergeOperation.php
new file mode 100644
index 0000000..87db2fb
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Catalogue/MergeOperation.php
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Catalogue;
+
+use Symfony\Component\Translation\MessageCatalogueInterface;
+
+/**
+ * Merge operation between two catalogues as follows:
+ * all = source ∪ target = {x: x ∈ source ∨ x ∈ target}
+ * new = all ∖ source = {x: x ∈ target ∧ x ∉ source}
+ * obsolete = source ∖ all = {x: x ∈ source ∧ x ∉ source ∧ x ∉ target} = ∅
+ * Basically, the result contains messages from both catalogues.
+ *
+ * @author Jean-François Simon <contact@jfsimon.fr>
+ */
+class MergeOperation extends AbstractOperation
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function processDomain(string $domain)
+ {
+ $this->messages[$domain] = [
+ 'all' => [],
+ 'new' => [],
+ 'obsolete' => [],
+ ];
+ $intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;
+
+ foreach ($this->source->all($domain) as $id => $message) {
+ $this->messages[$domain]['all'][$id] = $message;
+ $d = $this->source->defines($id, $intlDomain) ? $intlDomain : $domain;
+ $this->result->add([$id => $message], $d);
+ if (null !== $keyMetadata = $this->source->getMetadata($id, $d)) {
+ $this->result->setMetadata($id, $keyMetadata, $d);
+ }
+ }
+
+ foreach ($this->target->all($domain) as $id => $message) {
+ if (!$this->source->has($id, $domain)) {
+ $this->messages[$domain]['all'][$id] = $message;
+ $this->messages[$domain]['new'][$id] = $message;
+ $d = $this->target->defines($id, $intlDomain) ? $intlDomain : $domain;
+ $this->result->add([$id => $message], $d);
+ if (null !== $keyMetadata = $this->target->getMetadata($id, $d)) {
+ $this->result->setMetadata($id, $keyMetadata, $d);
+ }
+ }
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Catalogue/OperationInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Catalogue/OperationInterface.php
new file mode 100644
index 0000000..9ffac88
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Catalogue/OperationInterface.php
@@ -0,0 +1,71 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Catalogue;
+
+use Symfony\Component\Translation\MessageCatalogueInterface;
+
+/**
+ * Represents an operation on catalogue(s).
+ *
+ * An instance of this interface performs an operation on one or more catalogues and
+ * stores intermediate and final results of the operation.
+ *
+ * The first catalogue in its argument(s) is called the 'source catalogue' or 'source' and
+ * the following results are stored:
+ *
+ * Messages: also called 'all', are valid messages for the given domain after the operation is performed.
+ *
+ * New Messages: also called 'new' (new = all ∖ source = {x: x ∈ all ∧ x ∉ source}).
+ *
+ * Obsolete Messages: also called 'obsolete' (obsolete = source ∖ all = {x: x ∈ source ∧ x ∉ all}).
+ *
+ * Result: also called 'result', is the resulting catalogue for the given domain that holds the same messages as 'all'.
+ *
+ * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
+ */
+interface OperationInterface
+{
+ /**
+ * Returns domains affected by operation.
+ *
+ * @return array
+ */
+ public function getDomains();
+
+ /**
+ * Returns all valid messages ('all') after operation.
+ *
+ * @return array
+ */
+ public function getMessages(string $domain);
+
+ /**
+ * Returns new messages ('new') after operation.
+ *
+ * @return array
+ */
+ public function getNewMessages(string $domain);
+
+ /**
+ * Returns obsolete messages ('obsolete') after operation.
+ *
+ * @return array
+ */
+ public function getObsoleteMessages(string $domain);
+
+ /**
+ * Returns resulting catalogue ('result').
+ *
+ * @return MessageCatalogueInterface
+ */
+ public function getResult();
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Catalogue/TargetOperation.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Catalogue/TargetOperation.php
new file mode 100644
index 0000000..399d917
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Catalogue/TargetOperation.php
@@ -0,0 +1,74 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Catalogue;
+
+use Symfony\Component\Translation\MessageCatalogueInterface;
+
+/**
+ * Target operation between two catalogues:
+ * intersection = source ∩ target = {x: x ∈ source ∧ x ∈ target}
+ * all = intersection ∪ (target ∖ intersection) = target
+ * new = all ∖ source = {x: x ∈ target ∧ x ∉ source}
+ * obsolete = source ∖ all = source ∖ target = {x: x ∈ source ∧ x ∉ target}
+ * Basically, the result contains messages from the target catalogue.
+ *
+ * @author Michael Lee <michael.lee@zerustech.com>
+ */
+class TargetOperation extends AbstractOperation
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function processDomain(string $domain)
+ {
+ $this->messages[$domain] = [
+ 'all' => [],
+ 'new' => [],
+ 'obsolete' => [],
+ ];
+ $intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;
+
+ // For 'all' messages, the code can't be simplified as ``$this->messages[$domain]['all'] = $target->all($domain);``,
+ // because doing so will drop messages like {x: x ∈ source ∧ x ∉ target.all ∧ x ∈ target.fallback}
+ //
+ // For 'new' messages, the code can't be simplified as ``array_diff_assoc($this->target->all($domain), $this->source->all($domain));``
+ // because doing so will not exclude messages like {x: x ∈ target ∧ x ∉ source.all ∧ x ∈ source.fallback}
+ //
+ // For 'obsolete' messages, the code can't be simplified as ``array_diff_assoc($this->source->all($domain), $this->target->all($domain))``
+ // because doing so will not exclude messages like {x: x ∈ source ∧ x ∉ target.all ∧ x ∈ target.fallback}
+
+ foreach ($this->source->all($domain) as $id => $message) {
+ if ($this->target->has($id, $domain)) {
+ $this->messages[$domain]['all'][$id] = $message;
+ $d = $this->target->defines($id, $intlDomain) ? $intlDomain : $domain;
+ $this->result->add([$id => $message], $d);
+ if (null !== $keyMetadata = $this->source->getMetadata($id, $d)) {
+ $this->result->setMetadata($id, $keyMetadata, $d);
+ }
+ } else {
+ $this->messages[$domain]['obsolete'][$id] = $message;
+ }
+ }
+
+ foreach ($this->target->all($domain) as $id => $message) {
+ if (!$this->source->has($id, $domain)) {
+ $this->messages[$domain]['all'][$id] = $message;
+ $this->messages[$domain]['new'][$id] = $message;
+ $d = $this->target->defines($id, $intlDomain) ? $intlDomain : $domain;
+ $this->result->add([$id => $message], $d);
+ if (null !== $keyMetadata = $this->target->getMetadata($id, $d)) {
+ $this->result->setMetadata($id, $keyMetadata, $d);
+ }
+ }
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Command/TranslationPullCommand.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Command/TranslationPullCommand.php
new file mode 100644
index 0000000..0ec02ca
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Command/TranslationPullCommand.php
@@ -0,0 +1,157 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Command;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+use Symfony\Component\Translation\Catalogue\TargetOperation;
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Provider\TranslationProviderCollection;
+use Symfony\Component\Translation\Reader\TranslationReaderInterface;
+use Symfony\Component\Translation\Writer\TranslationWriterInterface;
+
+/**
+ * @author Mathieu Santostefano <msantostefano@protonmail.com>
+ *
+ * @experimental in 5.3
+ */
+final class TranslationPullCommand extends Command
+{
+ use TranslationTrait;
+
+ protected static $defaultName = 'translation:pull';
+ protected static $defaultDescription = 'Pull translations from a given provider.';
+
+ private $providerCollection;
+ private $writer;
+ private $reader;
+ private $defaultLocale;
+ private $transPaths;
+ private $enabledLocales;
+
+ public function __construct(TranslationProviderCollection $providerCollection, TranslationWriterInterface $writer, TranslationReaderInterface $reader, string $defaultLocale, array $transPaths = [], array $enabledLocales = [])
+ {
+ $this->providerCollection = $providerCollection;
+ $this->writer = $writer;
+ $this->reader = $reader;
+ $this->defaultLocale = $defaultLocale;
+ $this->transPaths = $transPaths;
+ $this->enabledLocales = $enabledLocales;
+
+ parent::__construct();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function configure()
+ {
+ $keys = $this->providerCollection->keys();
+ $defaultProvider = 1 === \count($keys) ? $keys[0] : null;
+
+ $this
+ ->setDefinition([
+ new InputArgument('provider', null !== $defaultProvider ? InputArgument::OPTIONAL : InputArgument::REQUIRED, 'The provider to pull translations from.', $defaultProvider),
+ new InputOption('force', null, InputOption::VALUE_NONE, 'Override existing translations with provider ones (it will delete not synchronized messages).'),
+ new InputOption('intl-icu', null, InputOption::VALUE_NONE, 'Associated to --force option, it will write messages in "%domain%+intl-icu.%locale%.xlf" files.'),
+ new InputOption('domains', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the domains to pull.'),
+ new InputOption('locales', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the locales to pull.'),
+ new InputOption('format', null, InputOption::VALUE_OPTIONAL, 'Override the default output format.', 'xlf12'),
+ ])
+ ->setHelp(<<<'EOF'
+The <info>%command.name%</> command pulls translations from the given provider. Only
+new translations are pulled, existing ones are not overwritten.
+
+You can overwrite existing translations (and remove the missing ones on local side) by using the <comment>--force</> flag:
+
+ <info>php %command.full_name% --force provider</>
+
+Full example:
+
+ <info>php %command.full_name% provider --force --domains=messages,validators --locales=en</>
+
+This command pulls all translations associated with the <comment>messages</> and <comment>validators</> domains for the <comment>en</> locale.
+Local translations for the specified domains and locale are deleted if they're not present on the provider and overwritten if it's the case.
+Local translations for others domains and locales are ignored.
+EOF
+ )
+ ;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function execute(InputInterface $input, OutputInterface $output): int
+ {
+ $io = new SymfonyStyle($input, $output);
+
+ $provider = $this->providerCollection->get($input->getArgument('provider'));
+ $force = $input->getOption('force');
+ $intlIcu = $input->getOption('intl-icu');
+ $locales = $input->getOption('locales') ?: $this->enabledLocales;
+ $domains = $input->getOption('domains');
+ $format = $input->getOption('format');
+ $xliffVersion = '1.2';
+
+ if ($intlIcu && !$force) {
+ $io->note('--intl-icu option only has an effect when used with --force. Here, it will be ignored.');
+ }
+
+ switch ($format) {
+ case 'xlf20': $xliffVersion = '2.0';
+ // no break
+ case 'xlf12': $format = 'xlf';
+ }
+
+ $writeOptions = [
+ 'path' => end($this->transPaths),
+ 'xliff_version' => $xliffVersion,
+ ];
+
+ if (!$domains) {
+ $domains = $provider->getDomains();
+ }
+
+ $providerTranslations = $provider->read($domains, $locales);
+
+ if ($force) {
+ foreach ($providerTranslations->getCatalogues() as $catalogue) {
+ $operation = new TargetOperation((new MessageCatalogue($catalogue->getLocale())), $catalogue);
+ if ($intlIcu) {
+ $operation->moveMessagesToIntlDomainsIfPossible();
+ }
+ $this->writer->write($operation->getResult(), $format, $writeOptions);
+ }
+
+ $io->success(sprintf('Local translations has been updated from "%s" (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
+
+ return 0;
+ }
+
+ $localTranslations = $this->readLocalTranslations($locales, $domains, $this->transPaths);
+
+ // Append pulled translations to local ones.
+ $localTranslations->addBag($providerTranslations->diff($localTranslations));
+
+ foreach ($localTranslations->getCatalogues() as $catalogue) {
+ $this->writer->write($catalogue, $format, $writeOptions);
+ }
+
+ $io->success(sprintf('New translations from "%s" has been written locally (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
+
+ return 0;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Command/TranslationPushCommand.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Command/TranslationPushCommand.php
new file mode 100644
index 0000000..b28d3e1
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Command/TranslationPushCommand.php
@@ -0,0 +1,158 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Command;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Exception\InvalidArgumentException;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+use Symfony\Component\Translation\Provider\TranslationProviderCollection;
+use Symfony\Component\Translation\Reader\TranslationReaderInterface;
+use Symfony\Component\Translation\TranslatorBag;
+
+/**
+ * @author Mathieu Santostefano <msantostefano@protonmail.com>
+ *
+ * @experimental in 5.3
+ */
+final class TranslationPushCommand extends Command
+{
+ use TranslationTrait;
+
+ protected static $defaultName = 'translation:push';
+ protected static $defaultDescription = 'Push translations to a given provider.';
+
+ private $providers;
+ private $reader;
+ private $transPaths;
+ private $enabledLocales;
+
+ public function __construct(TranslationProviderCollection $providers, TranslationReaderInterface $reader, array $transPaths = [], array $enabledLocales = [])
+ {
+ $this->providers = $providers;
+ $this->reader = $reader;
+ $this->transPaths = $transPaths;
+ $this->enabledLocales = $enabledLocales;
+
+ parent::__construct();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function configure()
+ {
+ $keys = $this->providers->keys();
+ $defaultProvider = 1 === \count($keys) ? $keys[0] : null;
+
+ $this
+ ->setDefinition([
+ new InputArgument('provider', null !== $defaultProvider ? InputArgument::OPTIONAL : InputArgument::REQUIRED, 'The provider to push translations to.', $defaultProvider),
+ new InputOption('force', null, InputOption::VALUE_NONE, 'Override existing translations with local ones (it will delete not synchronized messages).'),
+ new InputOption('delete-missing', null, InputOption::VALUE_NONE, 'Delete translations available on provider but not locally.'),
+ new InputOption('domains', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the domains to push.'),
+ new InputOption('locales', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Specify the locales to push.', $this->enabledLocales),
+ ])
+ ->setHelp(<<<'EOF'
+The <info>%command.name%</> command pushes translations to the given provider. Only new
+translations are pushed, existing ones are not overwritten.
+
+You can overwrite existing translations by using the <comment>--force</> flag:
+
+ <info>php %command.full_name% --force provider</>
+
+You can delete provider translations which are not present locally by using the <comment>--delete-missing</> flag:
+
+ <info>php %command.full_name% --delete-missing provider</>
+
+Full example:
+
+ <info>php %command.full_name% provider --force --delete-missing --domains=messages,validators --locales=en</>
+
+This command pushes all translations associated with the <comment>messages</> and <comment>validators</> domains for the <comment>en</> locale.
+Provider translations for the specified domains and locale are deleted if they're not present locally and overwritten if it's the case.
+Provider translations for others domains and locales are ignored.
+EOF
+ )
+ ;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function execute(InputInterface $input, OutputInterface $output): int
+ {
+ $provider = $this->providers->get($input->getArgument('provider'));
+
+ if (!$this->enabledLocales) {
+ throw new InvalidArgumentException(sprintf('You must define "framework.translator.enabled_locales" or "framework.translator.providers.%s.locales" config key in order to work with translation providers.', parse_url($provider, \PHP_URL_SCHEME)));
+ }
+
+ $io = new SymfonyStyle($input, $output);
+ $domains = $input->getOption('domains');
+ $locales = $input->getOption('locales');
+ $force = $input->getOption('force');
+ $deleteMissing = $input->getOption('delete-missing');
+
+ $localTranslations = $this->readLocalTranslations($locales, $domains, $this->transPaths);
+
+ if (!$domains) {
+ $domains = $this->getDomainsFromTranslatorBag($localTranslations);
+ }
+
+ if (!$deleteMissing && $force) {
+ $provider->write($localTranslations);
+
+ $io->success(sprintf('All local translations has been sent to "%s" (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
+
+ return 0;
+ }
+
+ $providerTranslations = $provider->read($domains, $locales);
+
+ if ($deleteMissing) {
+ $provider->delete($providerTranslations->diff($localTranslations));
+
+ $io->success(sprintf('Missing translations on "%s" has been deleted (for "%s" locale(s), and "%s" domain(s)).', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
+
+ // Read provider translations again, after missing translations deletion,
+ // to avoid push freshly deleted translations.
+ $providerTranslations = $provider->read($domains, $locales);
+ }
+
+ $translationsToWrite = $localTranslations->diff($providerTranslations);
+
+ if ($force) {
+ $translationsToWrite->addBag($localTranslations->intersect($providerTranslations));
+ }
+
+ $provider->write($translationsToWrite);
+
+ $io->success(sprintf('%s local translations has been sent to "%s" (for "%s" locale(s), and "%s" domain(s)).', $force ? 'All' : 'New', parse_url($provider, \PHP_URL_SCHEME), implode(', ', $locales), implode(', ', $domains)));
+
+ return 0;
+ }
+
+ private function getDomainsFromTranslatorBag(TranslatorBag $translatorBag): array
+ {
+ $domains = [];
+
+ foreach ($translatorBag->getCatalogues() as $catalogue) {
+ $domains += $catalogue->getDomains();
+ }
+
+ return array_unique($domains);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Command/TranslationTrait.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Command/TranslationTrait.php
new file mode 100644
index 0000000..6a2b1ba
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Command/TranslationTrait.php
@@ -0,0 +1,78 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Command;
+
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\MessageCatalogueInterface;
+use Symfony\Component\Translation\TranslatorBag;
+
+/**
+ * @internal
+ */
+trait TranslationTrait
+{
+ private function readLocalTranslations(array $locales, array $domains, array $transPaths): TranslatorBag
+ {
+ $bag = new TranslatorBag();
+
+ foreach ($locales as $locale) {
+ $catalogue = new MessageCatalogue($locale);
+ foreach ($transPaths as $path) {
+ $this->reader->read($path, $catalogue);
+ }
+
+ if ($domains) {
+ foreach ($domains as $domain) {
+ $catalogue = $this->filterCatalogue($catalogue, $domain);
+ $bag->addCatalogue($catalogue);
+ }
+ } else {
+ $bag->addCatalogue($catalogue);
+ }
+ }
+
+ return $bag;
+ }
+
+ private function filterCatalogue(MessageCatalogue $catalogue, string $domain): MessageCatalogue
+ {
+ $filteredCatalogue = new MessageCatalogue($catalogue->getLocale());
+
+ // extract intl-icu messages only
+ $intlDomain = $domain.MessageCatalogueInterface::INTL_DOMAIN_SUFFIX;
+ if ($intlMessages = $catalogue->all($intlDomain)) {
+ $filteredCatalogue->add($intlMessages, $intlDomain);
+ }
+
+ // extract all messages and subtract intl-icu messages
+ if ($messages = array_diff($catalogue->all($domain), $intlMessages)) {
+ $filteredCatalogue->add($messages, $domain);
+ }
+ foreach ($catalogue->getResources() as $resource) {
+ $filteredCatalogue->addResource($resource);
+ }
+
+ if ($metadata = $catalogue->getMetadata('', $intlDomain)) {
+ foreach ($metadata as $k => $v) {
+ $filteredCatalogue->setMetadata($k, $v, $intlDomain);
+ }
+ }
+
+ if ($metadata = $catalogue->getMetadata('', $domain)) {
+ foreach ($metadata as $k => $v) {
+ $filteredCatalogue->setMetadata($k, $v, $domain);
+ }
+ }
+
+ return $filteredCatalogue;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Command/XliffLintCommand.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Command/XliffLintCommand.php
new file mode 100644
index 0000000..4117d87
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Command/XliffLintCommand.php
@@ -0,0 +1,267 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Command;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Exception\RuntimeException;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\Util\XliffUtils;
+
+/**
+ * Validates XLIFF files syntax and outputs encountered errors.
+ *
+ * @author Grégoire Pineau <lyrixx@lyrixx.info>
+ * @author Robin Chalas <robin.chalas@gmail.com>
+ * @author Javier Eguiluz <javier.eguiluz@gmail.com>
+ */
+class XliffLintCommand extends Command
+{
+ protected static $defaultName = 'lint:xliff';
+ protected static $defaultDescription = 'Lint an XLIFF file and outputs encountered errors';
+
+ private $format;
+ private $displayCorrectFiles;
+ private $directoryIteratorProvider;
+ private $isReadableProvider;
+ private $requireStrictFileNames;
+
+ public function __construct(string $name = null, callable $directoryIteratorProvider = null, callable $isReadableProvider = null, bool $requireStrictFileNames = true)
+ {
+ parent::__construct($name);
+
+ $this->directoryIteratorProvider = $directoryIteratorProvider;
+ $this->isReadableProvider = $isReadableProvider;
+ $this->requireStrictFileNames = $requireStrictFileNames;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function configure()
+ {
+ $this
+ ->setDescription(self::$defaultDescription)
+ ->addArgument('filename', InputArgument::IS_ARRAY, 'A file, a directory or "-" for reading from STDIN')
+ ->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt')
+ ->setHelp(<<<EOF
+The <info>%command.name%</info> command lints an XLIFF file and outputs to STDOUT
+the first encountered syntax error.
+
+You can validates XLIFF contents passed from STDIN:
+
+ <info>cat filename | php %command.full_name% -</info>
+
+You can also validate the syntax of a file:
+
+ <info>php %command.full_name% filename</info>
+
+Or of a whole directory:
+
+ <info>php %command.full_name% dirname</info>
+ <info>php %command.full_name% dirname --format=json</info>
+
+EOF
+ )
+ ;
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $io = new SymfonyStyle($input, $output);
+ $filenames = (array) $input->getArgument('filename');
+ $this->format = $input->getOption('format');
+ $this->displayCorrectFiles = $output->isVerbose();
+
+ if (['-'] === $filenames) {
+ return $this->display($io, [$this->validate(file_get_contents('php://stdin'))]);
+ }
+
+ if (!$filenames) {
+ throw new RuntimeException('Please provide a filename or pipe file content to STDIN.');
+ }
+
+ $filesInfo = [];
+ foreach ($filenames as $filename) {
+ if (!$this->isReadable($filename)) {
+ throw new RuntimeException(sprintf('File or directory "%s" is not readable.', $filename));
+ }
+
+ foreach ($this->getFiles($filename) as $file) {
+ $filesInfo[] = $this->validate(file_get_contents($file), $file);
+ }
+ }
+
+ return $this->display($io, $filesInfo);
+ }
+
+ private function validate(string $content, string $file = null): array
+ {
+ $errors = [];
+
+ // Avoid: Warning DOMDocument::loadXML(): Empty string supplied as input
+ if ('' === trim($content)) {
+ return ['file' => $file, 'valid' => true];
+ }
+
+ $internal = libxml_use_internal_errors(true);
+
+ $document = new \DOMDocument();
+ $document->loadXML($content);
+
+ if (null !== $targetLanguage = $this->getTargetLanguageFromFile($document)) {
+ $normalizedLocalePattern = sprintf('(%s|%s)', preg_quote($targetLanguage, '/'), preg_quote(str_replace('-', '_', $targetLanguage), '/'));
+ // strict file names require translation files to be named '____.locale.xlf'
+ // otherwise, both '____.locale.xlf' and 'locale.____.xlf' are allowed
+ // also, the regexp matching must be case-insensitive, as defined for 'target-language' values
+ // http://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html#target-language
+ $expectedFilenamePattern = $this->requireStrictFileNames ? sprintf('/^.*\.(?i:%s)\.(?:xlf|xliff)/', $normalizedLocalePattern) : sprintf('/^(?:.*\.(?i:%s)|(?i:%s)\..*)\.(?:xlf|xliff)/', $normalizedLocalePattern, $normalizedLocalePattern);
+
+ if (0 === preg_match($expectedFilenamePattern, basename($file))) {
+ $errors[] = [
+ 'line' => -1,
+ 'column' => -1,
+ 'message' => sprintf('There is a mismatch between the language included in the file name ("%s") and the "%s" value used in the "target-language" attribute of the file.', basename($file), $targetLanguage),
+ ];
+ }
+ }
+
+ foreach (XliffUtils::validateSchema($document) as $xmlError) {
+ $errors[] = [
+ 'line' => $xmlError['line'],
+ 'column' => $xmlError['column'],
+ 'message' => $xmlError['message'],
+ ];
+ }
+
+ libxml_clear_errors();
+ libxml_use_internal_errors($internal);
+
+ return ['file' => $file, 'valid' => 0 === \count($errors), 'messages' => $errors];
+ }
+
+ private function display(SymfonyStyle $io, array $files)
+ {
+ switch ($this->format) {
+ case 'txt':
+ return $this->displayTxt($io, $files);
+ case 'json':
+ return $this->displayJson($io, $files);
+ default:
+ throw new InvalidArgumentException(sprintf('The format "%s" is not supported.', $this->format));
+ }
+ }
+
+ private function displayTxt(SymfonyStyle $io, array $filesInfo)
+ {
+ $countFiles = \count($filesInfo);
+ $erroredFiles = 0;
+
+ foreach ($filesInfo as $info) {
+ if ($info['valid'] && $this->displayCorrectFiles) {
+ $io->comment('<info>OK</info>'.($info['file'] ? sprintf(' in %s', $info['file']) : ''));
+ } elseif (!$info['valid']) {
+ ++$erroredFiles;
+ $io->text('<error> ERROR </error>'.($info['file'] ? sprintf(' in %s', $info['file']) : ''));
+ $io->listing(array_map(function ($error) {
+ // general document errors have a '-1' line number
+ return -1 === $error['line'] ? $error['message'] : sprintf('Line %d, Column %d: %s', $error['line'], $error['column'], $error['message']);
+ }, $info['messages']));
+ }
+ }
+
+ if (0 === $erroredFiles) {
+ $io->success(sprintf('All %d XLIFF files contain valid syntax.', $countFiles));
+ } else {
+ $io->warning(sprintf('%d XLIFF files have valid syntax and %d contain errors.', $countFiles - $erroredFiles, $erroredFiles));
+ }
+
+ return min($erroredFiles, 1);
+ }
+
+ private function displayJson(SymfonyStyle $io, array $filesInfo)
+ {
+ $errors = 0;
+
+ array_walk($filesInfo, function (&$v) use (&$errors) {
+ $v['file'] = (string) $v['file'];
+ if (!$v['valid']) {
+ ++$errors;
+ }
+ });
+
+ $io->writeln(json_encode($filesInfo, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES));
+
+ return min($errors, 1);
+ }
+
+ private function getFiles(string $fileOrDirectory)
+ {
+ if (is_file($fileOrDirectory)) {
+ yield new \SplFileInfo($fileOrDirectory);
+
+ return;
+ }
+
+ foreach ($this->getDirectoryIterator($fileOrDirectory) as $file) {
+ if (!\in_array($file->getExtension(), ['xlf', 'xliff'])) {
+ continue;
+ }
+
+ yield $file;
+ }
+ }
+
+ private function getDirectoryIterator(string $directory)
+ {
+ $default = function ($directory) {
+ return new \RecursiveIteratorIterator(
+ new \RecursiveDirectoryIterator($directory, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS),
+ \RecursiveIteratorIterator::LEAVES_ONLY
+ );
+ };
+
+ if (null !== $this->directoryIteratorProvider) {
+ return ($this->directoryIteratorProvider)($directory, $default);
+ }
+
+ return $default($directory);
+ }
+
+ private function isReadable(string $fileOrDirectory)
+ {
+ $default = function ($fileOrDirectory) {
+ return is_readable($fileOrDirectory);
+ };
+
+ if (null !== $this->isReadableProvider) {
+ return ($this->isReadableProvider)($fileOrDirectory, $default);
+ }
+
+ return $default($fileOrDirectory);
+ }
+
+ private function getTargetLanguageFromFile(\DOMDocument $xliffContents): ?string
+ {
+ foreach ($xliffContents->getElementsByTagName('file')[0]->attributes ?? [] as $attribute) {
+ if ('target-language' === $attribute->nodeName) {
+ return $attribute->nodeValue;
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DataCollector/TranslationDataCollector.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DataCollector/TranslationDataCollector.php
new file mode 100644
index 0000000..f8480ad
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DataCollector/TranslationDataCollector.php
@@ -0,0 +1,172 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\DataCollector;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\DataCollector\DataCollector;
+use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
+use Symfony\Component\Translation\DataCollectorTranslator;
+use Symfony\Component\VarDumper\Cloner\Data;
+
+/**
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ *
+ * @final
+ */
+class TranslationDataCollector extends DataCollector implements LateDataCollectorInterface
+{
+ private $translator;
+
+ public function __construct(DataCollectorTranslator $translator)
+ {
+ $this->translator = $translator;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function lateCollect()
+ {
+ $messages = $this->sanitizeCollectedMessages($this->translator->getCollectedMessages());
+
+ $this->data += $this->computeCount($messages);
+ $this->data['messages'] = $messages;
+
+ $this->data = $this->cloneVar($this->data);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function collect(Request $request, Response $response, \Throwable $exception = null)
+ {
+ $this->data['locale'] = $this->translator->getLocale();
+ $this->data['fallback_locales'] = $this->translator->getFallbackLocales();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function reset()
+ {
+ $this->data = [];
+ }
+
+ /**
+ * @return array|Data
+ */
+ public function getMessages()
+ {
+ return $this->data['messages'] ?? [];
+ }
+
+ /**
+ * @return int
+ */
+ public function getCountMissings()
+ {
+ return $this->data[DataCollectorTranslator::MESSAGE_MISSING] ?? 0;
+ }
+
+ /**
+ * @return int
+ */
+ public function getCountFallbacks()
+ {
+ return $this->data[DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK] ?? 0;
+ }
+
+ /**
+ * @return int
+ */
+ public function getCountDefines()
+ {
+ return $this->data[DataCollectorTranslator::MESSAGE_DEFINED] ?? 0;
+ }
+
+ public function getLocale()
+ {
+ return !empty($this->data['locale']) ? $this->data['locale'] : null;
+ }
+
+ /**
+ * @internal
+ */
+ public function getFallbackLocales()
+ {
+ return (isset($this->data['fallback_locales']) && \count($this->data['fallback_locales']) > 0) ? $this->data['fallback_locales'] : [];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'translation';
+ }
+
+ private function sanitizeCollectedMessages(array $messages)
+ {
+ $result = [];
+ foreach ($messages as $key => $message) {
+ $messageId = $message['locale'].$message['domain'].$message['id'];
+
+ if (!isset($result[$messageId])) {
+ $message['count'] = 1;
+ $message['parameters'] = !empty($message['parameters']) ? [$message['parameters']] : [];
+ $messages[$key]['translation'] = $this->sanitizeString($message['translation']);
+ $result[$messageId] = $message;
+ } else {
+ if (!empty($message['parameters'])) {
+ $result[$messageId]['parameters'][] = $message['parameters'];
+ }
+
+ ++$result[$messageId]['count'];
+ }
+
+ unset($messages[$key]);
+ }
+
+ return $result;
+ }
+
+ private function computeCount(array $messages)
+ {
+ $count = [
+ DataCollectorTranslator::MESSAGE_DEFINED => 0,
+ DataCollectorTranslator::MESSAGE_MISSING => 0,
+ DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK => 0,
+ ];
+
+ foreach ($messages as $message) {
+ ++$count[$message['state']];
+ }
+
+ return $count;
+ }
+
+ private function sanitizeString(string $string, int $length = 80)
+ {
+ $string = trim(preg_replace('/\s+/', ' ', $string));
+
+ if (false !== $encoding = mb_detect_encoding($string, null, true)) {
+ if (mb_strlen($string, $encoding) > $length) {
+ return mb_substr($string, 0, $length - 3, $encoding).'...';
+ }
+ } elseif (\strlen($string) > $length) {
+ return substr($string, 0, $length - 3).'...';
+ }
+
+ return $string;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DataCollectorTranslator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DataCollectorTranslator.php
new file mode 100644
index 0000000..c7d3597
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DataCollectorTranslator.php
@@ -0,0 +1,171 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Contracts\Translation\LocaleAwareInterface;
+use Symfony\Contracts\Translation\TranslatorInterface;
+
+/**
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+class DataCollectorTranslator implements TranslatorInterface, TranslatorBagInterface, LocaleAwareInterface, WarmableInterface
+{
+ public const MESSAGE_DEFINED = 0;
+ public const MESSAGE_MISSING = 1;
+ public const MESSAGE_EQUALS_FALLBACK = 2;
+
+ /**
+ * @var TranslatorInterface|TranslatorBagInterface
+ */
+ private $translator;
+
+ private $messages = [];
+
+ /**
+ * @param TranslatorInterface $translator The translator must implement TranslatorBagInterface
+ */
+ public function __construct(TranslatorInterface $translator)
+ {
+ if (!$translator instanceof TranslatorBagInterface || !$translator instanceof LocaleAwareInterface) {
+ throw new InvalidArgumentException(sprintf('The Translator "%s" must implement TranslatorInterface, TranslatorBagInterface and LocaleAwareInterface.', get_debug_type($translator)));
+ }
+
+ $this->translator = $translator;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function trans(?string $id, array $parameters = [], string $domain = null, string $locale = null)
+ {
+ $trans = $this->translator->trans($id = (string) $id, $parameters, $domain, $locale);
+ $this->collectMessage($locale, $domain, $id, $trans, $parameters);
+
+ return $trans;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setLocale(string $locale)
+ {
+ $this->translator->setLocale($locale);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getLocale()
+ {
+ return $this->translator->getLocale();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCatalogue(string $locale = null)
+ {
+ return $this->translator->getCatalogue($locale);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCatalogues(): array
+ {
+ return $this->translator->getCatalogues();
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return string[]
+ */
+ public function warmUp(string $cacheDir)
+ {
+ if ($this->translator instanceof WarmableInterface) {
+ return (array) $this->translator->warmUp($cacheDir);
+ }
+
+ return [];
+ }
+
+ /**
+ * Gets the fallback locales.
+ *
+ * @return array The fallback locales
+ */
+ public function getFallbackLocales()
+ {
+ if ($this->translator instanceof Translator || method_exists($this->translator, 'getFallbackLocales')) {
+ return $this->translator->getFallbackLocales();
+ }
+
+ return [];
+ }
+
+ /**
+ * Passes through all unknown calls onto the translator object.
+ */
+ public function __call(string $method, array $args)
+ {
+ return $this->translator->{$method}(...$args);
+ }
+
+ /**
+ * @return array
+ */
+ public function getCollectedMessages()
+ {
+ return $this->messages;
+ }
+
+ private function collectMessage(?string $locale, ?string $domain, string $id, string $translation, ?array $parameters = [])
+ {
+ if (null === $domain) {
+ $domain = 'messages';
+ }
+
+ $catalogue = $this->translator->getCatalogue($locale);
+ $locale = $catalogue->getLocale();
+ $fallbackLocale = null;
+ if ($catalogue->defines($id, $domain)) {
+ $state = self::MESSAGE_DEFINED;
+ } elseif ($catalogue->has($id, $domain)) {
+ $state = self::MESSAGE_EQUALS_FALLBACK;
+
+ $fallbackCatalogue = $catalogue->getFallbackCatalogue();
+ while ($fallbackCatalogue) {
+ if ($fallbackCatalogue->defines($id, $domain)) {
+ $fallbackLocale = $fallbackCatalogue->getLocale();
+ break;
+ }
+ $fallbackCatalogue = $fallbackCatalogue->getFallbackCatalogue();
+ }
+ } else {
+ $state = self::MESSAGE_MISSING;
+ }
+
+ $this->messages[] = [
+ 'locale' => $locale,
+ 'fallbackLocale' => $fallbackLocale,
+ 'domain' => $domain,
+ 'id' => $id,
+ 'translation' => $translation,
+ 'parameters' => $parameters,
+ 'state' => $state,
+ 'transChoiceNumber' => isset($parameters['%count%']) && is_numeric($parameters['%count%']) ? $parameters['%count%'] : null,
+ ];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslationDumperPass.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslationDumperPass.php
new file mode 100644
index 0000000..6d78342
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslationDumperPass.php
@@ -0,0 +1,48 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * Adds tagged translation.formatter services to translation writer.
+ */
+class TranslationDumperPass implements CompilerPassInterface
+{
+ private $writerServiceId;
+ private $dumperTag;
+
+ public function __construct(string $writerServiceId = 'translation.writer', string $dumperTag = 'translation.dumper')
+ {
+ if (1 < \func_num_args()) {
+ trigger_deprecation('symfony/translation', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
+ }
+
+ $this->writerServiceId = $writerServiceId;
+ $this->dumperTag = $dumperTag;
+ }
+
+ public function process(ContainerBuilder $container)
+ {
+ if (!$container->hasDefinition($this->writerServiceId)) {
+ return;
+ }
+
+ $definition = $container->getDefinition($this->writerServiceId);
+
+ foreach ($container->findTaggedServiceIds($this->dumperTag, true) as $id => $attributes) {
+ $definition->addMethodCall('addDumper', [$attributes[0]['alias'], new Reference($id)]);
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslationExtractorPass.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslationExtractorPass.php
new file mode 100644
index 0000000..fab6b20
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslationExtractorPass.php
@@ -0,0 +1,53 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * Adds tagged translation.extractor services to translation extractor.
+ */
+class TranslationExtractorPass implements CompilerPassInterface
+{
+ private $extractorServiceId;
+ private $extractorTag;
+
+ public function __construct(string $extractorServiceId = 'translation.extractor', string $extractorTag = 'translation.extractor')
+ {
+ if (0 < \func_num_args()) {
+ trigger_deprecation('symfony/translation', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
+ }
+
+ $this->extractorServiceId = $extractorServiceId;
+ $this->extractorTag = $extractorTag;
+ }
+
+ public function process(ContainerBuilder $container)
+ {
+ if (!$container->hasDefinition($this->extractorServiceId)) {
+ return;
+ }
+
+ $definition = $container->getDefinition($this->extractorServiceId);
+
+ foreach ($container->findTaggedServiceIds($this->extractorTag, true) as $id => $attributes) {
+ if (!isset($attributes[0]['alias'])) {
+ throw new RuntimeException(sprintf('The alias for the tag "translation.extractor" of service "%s" must be set.', $id));
+ }
+
+ $definition->addMethodCall('addExtractor', [$attributes[0]['alias'], new Reference($id)]);
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslatorPass.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslatorPass.php
new file mode 100644
index 0000000..c6a1306
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslatorPass.php
@@ -0,0 +1,93 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+
+class TranslatorPass implements CompilerPassInterface
+{
+ private $translatorServiceId;
+ private $readerServiceId;
+ private $loaderTag;
+ private $debugCommandServiceId;
+ private $updateCommandServiceId;
+
+ public function __construct(string $translatorServiceId = 'translator.default', string $readerServiceId = 'translation.reader', string $loaderTag = 'translation.loader', string $debugCommandServiceId = 'console.command.translation_debug', string $updateCommandServiceId = 'console.command.translation_update')
+ {
+ if (0 < \func_num_args()) {
+ trigger_deprecation('symfony/translation', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
+ }
+
+ $this->translatorServiceId = $translatorServiceId;
+ $this->readerServiceId = $readerServiceId;
+ $this->loaderTag = $loaderTag;
+ $this->debugCommandServiceId = $debugCommandServiceId;
+ $this->updateCommandServiceId = $updateCommandServiceId;
+ }
+
+ public function process(ContainerBuilder $container)
+ {
+ if (!$container->hasDefinition($this->translatorServiceId)) {
+ return;
+ }
+
+ $loaders = [];
+ $loaderRefs = [];
+ foreach ($container->findTaggedServiceIds($this->loaderTag, true) as $id => $attributes) {
+ $loaderRefs[$id] = new Reference($id);
+ $loaders[$id][] = $attributes[0]['alias'];
+ if (isset($attributes[0]['legacy-alias'])) {
+ $loaders[$id][] = $attributes[0]['legacy-alias'];
+ }
+ }
+
+ if ($container->hasDefinition($this->readerServiceId)) {
+ $definition = $container->getDefinition($this->readerServiceId);
+ foreach ($loaders as $id => $formats) {
+ foreach ($formats as $format) {
+ $definition->addMethodCall('addLoader', [$format, $loaderRefs[$id]]);
+ }
+ }
+ }
+
+ $container
+ ->findDefinition($this->translatorServiceId)
+ ->replaceArgument(0, ServiceLocatorTagPass::register($container, $loaderRefs))
+ ->replaceArgument(3, $loaders)
+ ;
+
+ if (!$container->hasParameter('twig.default_path')) {
+ return;
+ }
+
+ $paths = array_keys($container->getDefinition('twig.template_iterator')->getArgument(1));
+ if ($container->hasDefinition($this->debugCommandServiceId)) {
+ $definition = $container->getDefinition($this->debugCommandServiceId);
+ $definition->replaceArgument(4, $container->getParameter('twig.default_path'));
+
+ if (\count($definition->getArguments()) > 6) {
+ $definition->replaceArgument(6, $paths);
+ }
+ }
+ if ($container->hasDefinition($this->updateCommandServiceId)) {
+ $definition = $container->getDefinition($this->updateCommandServiceId);
+ $definition->replaceArgument(5, $container->getParameter('twig.default_path'));
+
+ if (\count($definition->getArguments()) > 7) {
+ $definition->replaceArgument(7, $paths);
+ }
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslatorPathsPass.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslatorPathsPass.php
new file mode 100644
index 0000000..85b0fa4
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslatorPathsPass.php
@@ -0,0 +1,151 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\Compiler\AbstractRecursivePass;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\ServiceLocator;
+
+/**
+ * @author Yonel Ceruto <yonelceruto@gmail.com>
+ */
+class TranslatorPathsPass extends AbstractRecursivePass
+{
+ private $translatorServiceId;
+ private $debugCommandServiceId;
+ private $updateCommandServiceId;
+ private $resolverServiceId;
+ private $level = 0;
+ private $paths = [];
+ private $definitions = [];
+ private $controllers = [];
+
+ public function __construct(string $translatorServiceId = 'translator', string $debugCommandServiceId = 'console.command.translation_debug', string $updateCommandServiceId = 'console.command.translation_update', string $resolverServiceId = 'argument_resolver.service')
+ {
+ if (0 < \func_num_args()) {
+ trigger_deprecation('symfony/translation', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
+ }
+
+ $this->translatorServiceId = $translatorServiceId;
+ $this->debugCommandServiceId = $debugCommandServiceId;
+ $this->updateCommandServiceId = $updateCommandServiceId;
+ $this->resolverServiceId = $resolverServiceId;
+ }
+
+ public function process(ContainerBuilder $container)
+ {
+ if (!$container->hasDefinition($this->translatorServiceId)) {
+ return;
+ }
+
+ foreach ($this->findControllerArguments($container) as $controller => $argument) {
+ $id = substr($controller, 0, strpos($controller, ':') ?: \strlen($controller));
+ if ($container->hasDefinition($id)) {
+ [$locatorRef] = $argument->getValues();
+ $this->controllers[(string) $locatorRef][$container->getDefinition($id)->getClass()] = true;
+ }
+ }
+
+ try {
+ parent::process($container);
+
+ $paths = [];
+ foreach ($this->paths as $class => $_) {
+ if (($r = $container->getReflectionClass($class)) && !$r->isInterface()) {
+ $paths[] = $r->getFileName();
+ foreach ($r->getTraits() as $trait) {
+ $paths[] = $trait->getFileName();
+ }
+ }
+ }
+ if ($paths) {
+ if ($container->hasDefinition($this->debugCommandServiceId)) {
+ $definition = $container->getDefinition($this->debugCommandServiceId);
+ $definition->replaceArgument(6, array_merge($definition->getArgument(6), $paths));
+ }
+ if ($container->hasDefinition($this->updateCommandServiceId)) {
+ $definition = $container->getDefinition($this->updateCommandServiceId);
+ $definition->replaceArgument(7, array_merge($definition->getArgument(7), $paths));
+ }
+ }
+ } finally {
+ $this->level = 0;
+ $this->paths = [];
+ $this->definitions = [];
+ }
+ }
+
+ protected function processValue($value, bool $isRoot = false)
+ {
+ if ($value instanceof Reference) {
+ if ((string) $value === $this->translatorServiceId) {
+ for ($i = $this->level - 1; $i >= 0; --$i) {
+ $class = $this->definitions[$i]->getClass();
+
+ if (ServiceLocator::class === $class) {
+ if (!isset($this->controllers[$this->currentId])) {
+ continue;
+ }
+ foreach ($this->controllers[$this->currentId] as $class => $_) {
+ $this->paths[$class] = true;
+ }
+ } else {
+ $this->paths[$class] = true;
+ }
+
+ break;
+ }
+ }
+
+ return $value;
+ }
+
+ if ($value instanceof Definition) {
+ $this->definitions[$this->level++] = $value;
+ $value = parent::processValue($value, $isRoot);
+ unset($this->definitions[--$this->level]);
+
+ return $value;
+ }
+
+ return parent::processValue($value, $isRoot);
+ }
+
+ private function findControllerArguments(ContainerBuilder $container): array
+ {
+ if ($container->hasDefinition($this->resolverServiceId)) {
+ $argument = $container->getDefinition($this->resolverServiceId)->getArgument(0);
+ if ($argument instanceof Reference) {
+ $argument = $container->getDefinition($argument);
+ }
+
+ return $argument->getArgument(0);
+ }
+
+ if ($container->hasDefinition('debug.'.$this->resolverServiceId)) {
+ $argument = $container->getDefinition('debug.'.$this->resolverServiceId)->getArgument(0);
+ if ($argument instanceof Reference) {
+ $argument = $container->getDefinition($argument);
+ }
+ $argument = $argument->getArgument(0);
+ if ($argument instanceof Reference) {
+ $argument = $container->getDefinition($argument);
+ }
+
+ return $argument->getArgument(0);
+ }
+
+ return [];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/CsvFileDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/CsvFileDumper.php
new file mode 100644
index 0000000..0c8589a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/CsvFileDumper.php
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * CsvFileDumper generates a csv formatted string representation of a message catalogue.
+ *
+ * @author Stealth35
+ */
+class CsvFileDumper extends FileDumper
+{
+ private $delimiter = ';';
+ private $enclosure = '"';
+
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = [])
+ {
+ $handle = fopen('php://memory', 'r+');
+
+ foreach ($messages->all($domain) as $source => $target) {
+ fputcsv($handle, [$source, $target], $this->delimiter, $this->enclosure);
+ }
+
+ rewind($handle);
+ $output = stream_get_contents($handle);
+ fclose($handle);
+
+ return $output;
+ }
+
+ /**
+ * Sets the delimiter and escape character for CSV.
+ */
+ public function setCsvControl(string $delimiter = ';', string $enclosure = '"')
+ {
+ $this->delimiter = $delimiter;
+ $this->enclosure = $enclosure;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'csv';
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/DumperInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/DumperInterface.php
new file mode 100644
index 0000000..7cdaef5
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/DumperInterface.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * DumperInterface is the interface implemented by all translation dumpers.
+ * There is no common option.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+interface DumperInterface
+{
+ /**
+ * Dumps the message catalogue.
+ *
+ * @param array $options Options that are used by the dumper
+ */
+ public function dump(MessageCatalogue $messages, array $options = []);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/FileDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/FileDumper.php
new file mode 100644
index 0000000..e257e72
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/FileDumper.php
@@ -0,0 +1,112 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\Exception\RuntimeException;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * FileDumper is an implementation of DumperInterface that dump a message catalogue to file(s).
+ *
+ * Options:
+ * - path (mandatory): the directory where the files should be saved
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+abstract class FileDumper implements DumperInterface
+{
+ /**
+ * A template for the relative paths to files.
+ *
+ * @var string
+ */
+ protected $relativePathTemplate = '%domain%.%locale%.%extension%';
+
+ /**
+ * Sets the template for the relative paths to files.
+ *
+ * @param string $relativePathTemplate A template for the relative paths to files
+ */
+ public function setRelativePathTemplate(string $relativePathTemplate)
+ {
+ $this->relativePathTemplate = $relativePathTemplate;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function dump(MessageCatalogue $messages, array $options = [])
+ {
+ if (!\array_key_exists('path', $options)) {
+ throw new InvalidArgumentException('The file dumper needs a path option.');
+ }
+
+ // save a file for each domain
+ foreach ($messages->getDomains() as $domain) {
+ $fullpath = $options['path'].'/'.$this->getRelativePath($domain, $messages->getLocale());
+ if (!file_exists($fullpath)) {
+ $directory = \dirname($fullpath);
+ if (!file_exists($directory) && !@mkdir($directory, 0777, true)) {
+ throw new RuntimeException(sprintf('Unable to create directory "%s".', $directory));
+ }
+ }
+
+ $intlDomain = $domain.MessageCatalogue::INTL_DOMAIN_SUFFIX;
+ $intlMessages = $messages->all($intlDomain);
+
+ if ($intlMessages) {
+ $intlPath = $options['path'].'/'.$this->getRelativePath($intlDomain, $messages->getLocale());
+ file_put_contents($intlPath, $this->formatCatalogue($messages, $intlDomain, $options));
+
+ $messages->replace([], $intlDomain);
+
+ try {
+ if ($messages->all($domain)) {
+ file_put_contents($fullpath, $this->formatCatalogue($messages, $domain, $options));
+ }
+ continue;
+ } finally {
+ $messages->replace($intlMessages, $intlDomain);
+ }
+ }
+
+ file_put_contents($fullpath, $this->formatCatalogue($messages, $domain, $options));
+ }
+ }
+
+ /**
+ * Transforms a domain of a message catalogue to its string representation.
+ *
+ * @return string representation
+ */
+ abstract public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = []);
+
+ /**
+ * Gets the file extension of the dumper.
+ *
+ * @return string file extension
+ */
+ abstract protected function getExtension();
+
+ /**
+ * Gets the relative file path using the template.
+ */
+ private function getRelativePath(string $domain, string $locale): string
+ {
+ return strtr($this->relativePathTemplate, [
+ '%domain%' => $domain,
+ '%locale%' => $locale,
+ '%extension%' => $this->getExtension(),
+ ]);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/IcuResFileDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/IcuResFileDumper.php
new file mode 100644
index 0000000..cdc5991
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/IcuResFileDumper.php
@@ -0,0 +1,104 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * IcuResDumper generates an ICU ResourceBundle formatted string representation of a message catalogue.
+ *
+ * @author Stealth35
+ */
+class IcuResFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected $relativePathTemplate = '%domain%/%locale%.%extension%';
+
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = [])
+ {
+ $data = $indexes = $resources = '';
+
+ foreach ($messages->all($domain) as $source => $target) {
+ $indexes .= pack('v', \strlen($data) + 28);
+ $data .= $source."\0";
+ }
+
+ $data .= $this->writePadding($data);
+
+ $keyTop = $this->getPosition($data);
+
+ foreach ($messages->all($domain) as $source => $target) {
+ $resources .= pack('V', $this->getPosition($data));
+
+ $data .= pack('V', \strlen($target))
+ .mb_convert_encoding($target."\0", 'UTF-16LE', 'UTF-8')
+ .$this->writePadding($data)
+ ;
+ }
+
+ $resOffset = $this->getPosition($data);
+
+ $data .= pack('v', \count($messages->all($domain)))
+ .$indexes
+ .$this->writePadding($data)
+ .$resources
+ ;
+
+ $bundleTop = $this->getPosition($data);
+
+ $root = pack('V7',
+ $resOffset + (2 << 28), // Resource Offset + Resource Type
+ 6, // Index length
+ $keyTop, // Index keys top
+ $bundleTop, // Index resources top
+ $bundleTop, // Index bundle top
+ \count($messages->all($domain)), // Index max table length
+ 0 // Index attributes
+ );
+
+ $header = pack('vC2v4C12@32',
+ 32, // Header size
+ 0xDA, 0x27, // Magic number 1 and 2
+ 20, 0, 0, 2, // Rest of the header, ..., Size of a char
+ 0x52, 0x65, 0x73, 0x42, // Data format identifier
+ 1, 2, 0, 0, // Data version
+ 1, 4, 0, 0 // Unicode version
+ );
+
+ return $header.$root.$data;
+ }
+
+ private function writePadding(string $data): ?string
+ {
+ $padding = \strlen($data) % 4;
+
+ return $padding ? str_repeat("\xAA", 4 - $padding) : null;
+ }
+
+ private function getPosition(string $data)
+ {
+ return (\strlen($data) + 28) / 4;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'res';
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/IniFileDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/IniFileDumper.php
new file mode 100644
index 0000000..93c900a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/IniFileDumper.php
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * IniFileDumper generates an ini formatted string representation of a message catalogue.
+ *
+ * @author Stealth35
+ */
+class IniFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = [])
+ {
+ $output = '';
+
+ foreach ($messages->all($domain) as $source => $target) {
+ $escapeTarget = str_replace('"', '\"', $target);
+ $output .= $source.'="'.$escapeTarget."\"\n";
+ }
+
+ return $output;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'ini';
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/JsonFileDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/JsonFileDumper.php
new file mode 100644
index 0000000..34c0b56
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/JsonFileDumper.php
@@ -0,0 +1,40 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * JsonFileDumper generates an json formatted string representation of a message catalogue.
+ *
+ * @author singles
+ */
+class JsonFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = [])
+ {
+ $flags = $options['json_encoding'] ?? \JSON_PRETTY_PRINT;
+
+ return json_encode($messages->all($domain), $flags);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'json';
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/MoFileDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/MoFileDumper.php
new file mode 100644
index 0000000..54d0da8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/MoFileDumper.php
@@ -0,0 +1,82 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\Loader\MoFileLoader;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * MoFileDumper generates a gettext formatted string representation of a message catalogue.
+ *
+ * @author Stealth35
+ */
+class MoFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = [])
+ {
+ $sources = $targets = $sourceOffsets = $targetOffsets = '';
+ $offsets = [];
+ $size = 0;
+
+ foreach ($messages->all($domain) as $source => $target) {
+ $offsets[] = array_map('strlen', [$sources, $source, $targets, $target]);
+ $sources .= "\0".$source;
+ $targets .= "\0".$target;
+ ++$size;
+ }
+
+ $header = [
+ 'magicNumber' => MoFileLoader::MO_LITTLE_ENDIAN_MAGIC,
+ 'formatRevision' => 0,
+ 'count' => $size,
+ 'offsetId' => MoFileLoader::MO_HEADER_SIZE,
+ 'offsetTranslated' => MoFileLoader::MO_HEADER_SIZE + (8 * $size),
+ 'sizeHashes' => 0,
+ 'offsetHashes' => MoFileLoader::MO_HEADER_SIZE + (16 * $size),
+ ];
+
+ $sourcesSize = \strlen($sources);
+ $sourcesStart = $header['offsetHashes'] + 1;
+
+ foreach ($offsets as $offset) {
+ $sourceOffsets .= $this->writeLong($offset[1])
+ .$this->writeLong($offset[0] + $sourcesStart);
+ $targetOffsets .= $this->writeLong($offset[3])
+ .$this->writeLong($offset[2] + $sourcesStart + $sourcesSize);
+ }
+
+ $output = implode('', array_map([$this, 'writeLong'], $header))
+ .$sourceOffsets
+ .$targetOffsets
+ .$sources
+ .$targets
+ ;
+
+ return $output;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'mo';
+ }
+
+ private function writeLong($str): string
+ {
+ return pack('V*', $str);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/PhpFileDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/PhpFileDumper.php
new file mode 100644
index 0000000..6163b52
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/PhpFileDumper.php
@@ -0,0 +1,38 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * PhpFileDumper generates PHP files from a message catalogue.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+class PhpFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = [])
+ {
+ return "<?php\n\nreturn ".var_export($messages->all($domain), true).";\n";
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'php';
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/PoFileDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/PoFileDumper.php
new file mode 100644
index 0000000..0d82281
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/PoFileDumper.php
@@ -0,0 +1,137 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * PoFileDumper generates a gettext formatted string representation of a message catalogue.
+ *
+ * @author Stealth35
+ */
+class PoFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = [])
+ {
+ $output = 'msgid ""'."\n";
+ $output .= 'msgstr ""'."\n";
+ $output .= '"Content-Type: text/plain; charset=UTF-8\n"'."\n";
+ $output .= '"Content-Transfer-Encoding: 8bit\n"'."\n";
+ $output .= '"Language: '.$messages->getLocale().'\n"'."\n";
+ $output .= "\n";
+
+ $newLine = false;
+ foreach ($messages->all($domain) as $source => $target) {
+ if ($newLine) {
+ $output .= "\n";
+ } else {
+ $newLine = true;
+ }
+ $metadata = $messages->getMetadata($source, $domain);
+
+ if (isset($metadata['comments'])) {
+ $output .= $this->formatComments($metadata['comments']);
+ }
+ if (isset($metadata['flags'])) {
+ $output .= $this->formatComments(implode(',', (array) $metadata['flags']), ',');
+ }
+ if (isset($metadata['sources'])) {
+ $output .= $this->formatComments(implode(' ', (array) $metadata['sources']), ':');
+ }
+
+ $sourceRules = $this->getStandardRules($source);
+ $targetRules = $this->getStandardRules($target);
+ if (2 == \count($sourceRules) && [] !== $targetRules) {
+ $output .= sprintf('msgid "%s"'."\n", $this->escape($sourceRules[0]));
+ $output .= sprintf('msgid_plural "%s"'."\n", $this->escape($sourceRules[1]));
+ foreach ($targetRules as $i => $targetRule) {
+ $output .= sprintf('msgstr[%d] "%s"'."\n", $i, $this->escape($targetRule));
+ }
+ } else {
+ $output .= sprintf('msgid "%s"'."\n", $this->escape($source));
+ $output .= sprintf('msgstr "%s"'."\n", $this->escape($target));
+ }
+ }
+
+ return $output;
+ }
+
+ private function getStandardRules(string $id)
+ {
+ // Partly copied from TranslatorTrait::trans.
+ $parts = [];
+ if (preg_match('/^\|++$/', $id)) {
+ $parts = explode('|', $id);
+ } elseif (preg_match_all('/(?:\|\||[^\|])++/', $id, $matches)) {
+ $parts = $matches[0];
+ }
+
+ $intervalRegexp = <<<'EOF'
+/^(?P<interval>
+ ({\s*
+ (\-?\d+(\.\d+)?[\s*,\s*\-?\d+(\.\d+)?]*)
+ \s*})
+
+ |
+
+ (?P<left_delimiter>[\[\]])
+ \s*
+ (?P<left>-Inf|\-?\d+(\.\d+)?)
+ \s*,\s*
+ (?P<right>\+?Inf|\-?\d+(\.\d+)?)
+ \s*
+ (?P<right_delimiter>[\[\]])
+)\s*(?P<message>.*?)$/xs
+EOF;
+
+ $standardRules = [];
+ foreach ($parts as $part) {
+ $part = trim(str_replace('||', '|', $part));
+
+ if (preg_match($intervalRegexp, $part)) {
+ // Explicit rule is not a standard rule.
+ return [];
+ } else {
+ $standardRules[] = $part;
+ }
+ }
+
+ return $standardRules;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'po';
+ }
+
+ private function escape(string $str): string
+ {
+ return addcslashes($str, "\0..\37\42\134");
+ }
+
+ private function formatComments($comments, string $prefix = ''): ?string
+ {
+ $output = null;
+
+ foreach ((array) $comments as $comment) {
+ $output .= sprintf('#%s %s'."\n", $prefix, $comment);
+ }
+
+ return $output;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/QtFileDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/QtFileDumper.php
new file mode 100644
index 0000000..406e9f0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/QtFileDumper.php
@@ -0,0 +1,61 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * QtFileDumper generates ts files from a message catalogue.
+ *
+ * @author Benjamin Eberlei <kontakt@beberlei.de>
+ */
+class QtFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = [])
+ {
+ $dom = new \DOMDocument('1.0', 'utf-8');
+ $dom->formatOutput = true;
+ $ts = $dom->appendChild($dom->createElement('TS'));
+ $context = $ts->appendChild($dom->createElement('context'));
+ $context->appendChild($dom->createElement('name', $domain));
+
+ foreach ($messages->all($domain) as $source => $target) {
+ $message = $context->appendChild($dom->createElement('message'));
+ $metadata = $messages->getMetadata($source, $domain);
+ if (isset($metadata['sources'])) {
+ foreach ((array) $metadata['sources'] as $location) {
+ $loc = explode(':', $location, 2);
+ $location = $message->appendChild($dom->createElement('location'));
+ $location->setAttribute('filename', $loc[0]);
+ if (isset($loc[1])) {
+ $location->setAttribute('line', $loc[1]);
+ }
+ }
+ }
+ $message->appendChild($dom->createElement('source', $source));
+ $message->appendChild($dom->createElement('translation', $target));
+ }
+
+ return $dom->saveXML();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'ts';
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/XliffFileDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/XliffFileDumper.php
new file mode 100644
index 0000000..f7dbdcd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/XliffFileDumper.php
@@ -0,0 +1,203 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * XliffFileDumper generates xliff files from a message catalogue.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+class XliffFileDumper extends FileDumper
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = [])
+ {
+ $xliffVersion = '1.2';
+ if (\array_key_exists('xliff_version', $options)) {
+ $xliffVersion = $options['xliff_version'];
+ }
+
+ if (\array_key_exists('default_locale', $options)) {
+ $defaultLocale = $options['default_locale'];
+ } else {
+ $defaultLocale = \Locale::getDefault();
+ }
+
+ if ('1.2' === $xliffVersion) {
+ return $this->dumpXliff1($defaultLocale, $messages, $domain, $options);
+ }
+ if ('2.0' === $xliffVersion) {
+ return $this->dumpXliff2($defaultLocale, $messages, $domain);
+ }
+
+ throw new InvalidArgumentException(sprintf('No support implemented for dumping XLIFF version "%s".', $xliffVersion));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return 'xlf';
+ }
+
+ private function dumpXliff1(string $defaultLocale, MessageCatalogue $messages, ?string $domain, array $options = [])
+ {
+ $toolInfo = ['tool-id' => 'symfony', 'tool-name' => 'Symfony'];
+ if (\array_key_exists('tool_info', $options)) {
+ $toolInfo = array_merge($toolInfo, $options['tool_info']);
+ }
+
+ $dom = new \DOMDocument('1.0', 'utf-8');
+ $dom->formatOutput = true;
+
+ $xliff = $dom->appendChild($dom->createElement('xliff'));
+ $xliff->setAttribute('version', '1.2');
+ $xliff->setAttribute('xmlns', 'urn:oasis:names:tc:xliff:document:1.2');
+
+ $xliffFile = $xliff->appendChild($dom->createElement('file'));
+ $xliffFile->setAttribute('source-language', str_replace('_', '-', $defaultLocale));
+ $xliffFile->setAttribute('target-language', str_replace('_', '-', $messages->getLocale()));
+ $xliffFile->setAttribute('datatype', 'plaintext');
+ $xliffFile->setAttribute('original', 'file.ext');
+
+ $xliffHead = $xliffFile->appendChild($dom->createElement('header'));
+ $xliffTool = $xliffHead->appendChild($dom->createElement('tool'));
+ foreach ($toolInfo as $id => $value) {
+ $xliffTool->setAttribute($id, $value);
+ }
+
+ $xliffBody = $xliffFile->appendChild($dom->createElement('body'));
+ foreach ($messages->all($domain) as $source => $target) {
+ $translation = $dom->createElement('trans-unit');
+
+ $translation->setAttribute('id', strtr(substr(base64_encode(hash('sha256', $source, true)), 0, 7), '/+', '._'));
+ $translation->setAttribute('resname', $source);
+
+ $s = $translation->appendChild($dom->createElement('source'));
+ $s->appendChild($dom->createTextNode($source));
+
+ // Does the target contain characters requiring a CDATA section?
+ $text = 1 === preg_match('/[&<>]/', $target) ? $dom->createCDATASection($target) : $dom->createTextNode($target);
+
+ $targetElement = $dom->createElement('target');
+ $metadata = $messages->getMetadata($source, $domain);
+ if ($this->hasMetadataArrayInfo('target-attributes', $metadata)) {
+ foreach ($metadata['target-attributes'] as $name => $value) {
+ $targetElement->setAttribute($name, $value);
+ }
+ }
+ $t = $translation->appendChild($targetElement);
+ $t->appendChild($text);
+
+ if ($this->hasMetadataArrayInfo('notes', $metadata)) {
+ foreach ($metadata['notes'] as $note) {
+ if (!isset($note['content'])) {
+ continue;
+ }
+
+ $n = $translation->appendChild($dom->createElement('note'));
+ $n->appendChild($dom->createTextNode($note['content']));
+
+ if (isset($note['priority'])) {
+ $n->setAttribute('priority', $note['priority']);
+ }
+
+ if (isset($note['from'])) {
+ $n->setAttribute('from', $note['from']);
+ }
+ }
+ }
+
+ $xliffBody->appendChild($translation);
+ }
+
+ return $dom->saveXML();
+ }
+
+ private function dumpXliff2(string $defaultLocale, MessageCatalogue $messages, ?string $domain)
+ {
+ $dom = new \DOMDocument('1.0', 'utf-8');
+ $dom->formatOutput = true;
+
+ $xliff = $dom->appendChild($dom->createElement('xliff'));
+ $xliff->setAttribute('xmlns', 'urn:oasis:names:tc:xliff:document:2.0');
+ $xliff->setAttribute('version', '2.0');
+ $xliff->setAttribute('srcLang', str_replace('_', '-', $defaultLocale));
+ $xliff->setAttribute('trgLang', str_replace('_', '-', $messages->getLocale()));
+
+ $xliffFile = $xliff->appendChild($dom->createElement('file'));
+ if (str_ends_with($domain, MessageCatalogue::INTL_DOMAIN_SUFFIX)) {
+ $xliffFile->setAttribute('id', substr($domain, 0, -\strlen(MessageCatalogue::INTL_DOMAIN_SUFFIX)).'.'.$messages->getLocale());
+ } else {
+ $xliffFile->setAttribute('id', $domain.'.'.$messages->getLocale());
+ }
+
+ foreach ($messages->all($domain) as $source => $target) {
+ $translation = $dom->createElement('unit');
+ $translation->setAttribute('id', strtr(substr(base64_encode(hash('sha256', $source, true)), 0, 7), '/+', '._'));
+
+ if (\strlen($source) <= 80) {
+ $translation->setAttribute('name', $source);
+ }
+
+ $metadata = $messages->getMetadata($source, $domain);
+
+ // Add notes section
+ if ($this->hasMetadataArrayInfo('notes', $metadata)) {
+ $notesElement = $dom->createElement('notes');
+ foreach ($metadata['notes'] as $note) {
+ $n = $dom->createElement('note');
+ $n->appendChild($dom->createTextNode($note['content'] ?? ''));
+ unset($note['content']);
+
+ foreach ($note as $name => $value) {
+ $n->setAttribute($name, $value);
+ }
+ $notesElement->appendChild($n);
+ }
+ $translation->appendChild($notesElement);
+ }
+
+ $segment = $translation->appendChild($dom->createElement('segment'));
+
+ $s = $segment->appendChild($dom->createElement('source'));
+ $s->appendChild($dom->createTextNode($source));
+
+ // Does the target contain characters requiring a CDATA section?
+ $text = 1 === preg_match('/[&<>]/', $target) ? $dom->createCDATASection($target) : $dom->createTextNode($target);
+
+ $targetElement = $dom->createElement('target');
+ if ($this->hasMetadataArrayInfo('target-attributes', $metadata)) {
+ foreach ($metadata['target-attributes'] as $name => $value) {
+ $targetElement->setAttribute($name, $value);
+ }
+ }
+ $t = $segment->appendChild($targetElement);
+ $t->appendChild($text);
+
+ $xliffFile->appendChild($translation);
+ }
+
+ return $dom->saveXML();
+ }
+
+ private function hasMetadataArrayInfo(string $key, array $metadata = null): bool
+ {
+ return is_iterable($metadata[$key] ?? null);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/YamlFileDumper.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/YamlFileDumper.php
new file mode 100644
index 0000000..0b21e8c
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Dumper/YamlFileDumper.php
@@ -0,0 +1,62 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Dumper;
+
+use Symfony\Component\Translation\Exception\LogicException;
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Util\ArrayConverter;
+use Symfony\Component\Yaml\Yaml;
+
+/**
+ * YamlFileDumper generates yaml files from a message catalogue.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+class YamlFileDumper extends FileDumper
+{
+ private $extension;
+
+ public function __construct(string $extension = 'yml')
+ {
+ $this->extension = $extension;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function formatCatalogue(MessageCatalogue $messages, string $domain, array $options = [])
+ {
+ if (!class_exists(Yaml::class)) {
+ throw new LogicException('Dumping translations in the YAML format requires the Symfony Yaml component.');
+ }
+
+ $data = $messages->all($domain);
+
+ if (isset($options['as_tree']) && $options['as_tree']) {
+ $data = ArrayConverter::expandToTree($data);
+ }
+
+ if (isset($options['inline']) && ($inline = (int) $options['inline']) > 0) {
+ return Yaml::dump($data, $inline);
+ }
+
+ return Yaml::dump($data);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getExtension()
+ {
+ return $this->extension;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/ExceptionInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/ExceptionInterface.php
new file mode 100644
index 0000000..8f9c54e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/ExceptionInterface.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+/**
+ * Exception interface for all exceptions thrown by the component.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface ExceptionInterface extends \Throwable
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/IncompleteDsnException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/IncompleteDsnException.php
new file mode 100644
index 0000000..cb0ce02
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/IncompleteDsnException.php
@@ -0,0 +1,24 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+class IncompleteDsnException extends InvalidArgumentException
+{
+ public function __construct(string $message, string $dsn = null, \Throwable $previous = null)
+ {
+ if ($dsn) {
+ $message = sprintf('Invalid "%s" provider DSN: ', $dsn).$message;
+ }
+
+ parent::__construct($message, 0, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/InvalidArgumentException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/InvalidArgumentException.php
new file mode 100644
index 0000000..90d0669
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/InvalidArgumentException.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+/**
+ * Base InvalidArgumentException for the Translation component.
+ *
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/InvalidResourceException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/InvalidResourceException.php
new file mode 100644
index 0000000..cf07943
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/InvalidResourceException.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+/**
+ * Thrown when a resource cannot be loaded.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class InvalidResourceException extends \InvalidArgumentException implements ExceptionInterface
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/LogicException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/LogicException.php
new file mode 100644
index 0000000..9019c7e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/LogicException.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+/**
+ * Base LogicException for Translation component.
+ *
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+class LogicException extends \LogicException implements ExceptionInterface
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/MissingRequiredOptionException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/MissingRequiredOptionException.php
new file mode 100644
index 0000000..2b5f808
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/MissingRequiredOptionException.php
@@ -0,0 +1,25 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+/**
+ * @author Oskar Stark <oskarstark@googlemail.com>
+ */
+class MissingRequiredOptionException extends IncompleteDsnException
+{
+ public function __construct(string $option, string $dsn = null, \Throwable $previous = null)
+ {
+ $message = sprintf('The option "%s" is required but missing.', $option);
+
+ parent::__construct($message, $dsn, $previous);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/NotFoundResourceException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/NotFoundResourceException.php
new file mode 100644
index 0000000..cff73ae
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/NotFoundResourceException.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+/**
+ * Thrown when a resource does not exist.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class NotFoundResourceException extends \InvalidArgumentException implements ExceptionInterface
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/ProviderException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/ProviderException.php
new file mode 100644
index 0000000..659c6d7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/ProviderException.php
@@ -0,0 +1,43 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+use Symfony\Contracts\HttpClient\ResponseInterface;
+
+/**
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @experimental in 5.3
+ */
+class ProviderException extends RuntimeException implements ProviderExceptionInterface
+{
+ private $response;
+ private $debug;
+
+ public function __construct(string $message, ResponseInterface $response, int $code = 0, \Exception $previous = null)
+ {
+ $this->response = $response;
+ $this->debug .= $response->getInfo('debug') ?? '';
+
+ parent::__construct($message, $code, $previous);
+ }
+
+ public function getResponse(): ResponseInterface
+ {
+ return $this->response;
+ }
+
+ public function getDebug(): string
+ {
+ return $this->debug;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/ProviderExceptionInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/ProviderExceptionInterface.php
new file mode 100644
index 0000000..8cf1c51
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/ProviderExceptionInterface.php
@@ -0,0 +1,25 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+/**
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @experimental in 5.3
+ */
+interface ProviderExceptionInterface extends ExceptionInterface
+{
+ /*
+ * Returns debug info coming from the Symfony\Contracts\HttpClient\ResponseInterface
+ */
+ public function getDebug(): string;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/RuntimeException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/RuntimeException.php
new file mode 100644
index 0000000..dcd7940
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/RuntimeException.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+/**
+ * Base RuntimeException for the Translation component.
+ *
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+class RuntimeException extends \RuntimeException implements ExceptionInterface
+{
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/UnsupportedSchemeException.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/UnsupportedSchemeException.php
new file mode 100644
index 0000000..7fbaa8f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Exception/UnsupportedSchemeException.php
@@ -0,0 +1,54 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Exception;
+
+use Symfony\Component\Translation\Bridge;
+use Symfony\Component\Translation\Provider\Dsn;
+
+class UnsupportedSchemeException extends LogicException
+{
+ private const SCHEME_TO_PACKAGE_MAP = [
+ 'crowdin' => [
+ 'class' => Bridge\Crowdin\CrowdinProviderFactory::class,
+ 'package' => 'symfony/crowdin-translation-provider',
+ ],
+ 'loco' => [
+ 'class' => Bridge\Loco\LocoProviderFactory::class,
+ 'package' => 'symfony/loco-translation-provider',
+ ],
+ 'lokalise' => [
+ 'class' => Bridge\Lokalise\LokaliseProviderFactory::class,
+ 'package' => 'symfony/lokalise-translation-provider',
+ ],
+ ];
+
+ public function __construct(Dsn $dsn, string $name = null, array $supported = [])
+ {
+ $provider = $dsn->getScheme();
+ if (false !== $pos = strpos($provider, '+')) {
+ $provider = substr($provider, 0, $pos);
+ }
+ $package = self::SCHEME_TO_PACKAGE_MAP[$provider] ?? null;
+ if ($package && !class_exists($package['class'])) {
+ parent::__construct(sprintf('Unable to synchronize translations via "%s" as the provider is not installed; try running "composer require %s".', $provider, $package['package']));
+
+ return;
+ }
+
+ $message = sprintf('The "%s" scheme is not supported', $dsn->getScheme());
+ if ($name && $supported) {
+ $message .= sprintf('; supported schemes for translation provider "%s" are: "%s"', $name, implode('", "', $supported));
+ }
+
+ parent::__construct($message.'.');
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/AbstractFileExtractor.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/AbstractFileExtractor.php
new file mode 100644
index 0000000..729dd17
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/AbstractFileExtractor.php
@@ -0,0 +1,76 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Extractor;
+
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+
+/**
+ * Base class used by classes that extract translation messages from files.
+ *
+ * @author Marcos D. Sánchez <marcosdsanchez@gmail.com>
+ */
+abstract class AbstractFileExtractor
+{
+ /**
+ * @param string|iterable $resource Files, a file or a directory
+ *
+ * @return iterable
+ */
+ protected function extractFiles($resource)
+ {
+ if (is_iterable($resource)) {
+ $files = [];
+ foreach ($resource as $file) {
+ if ($this->canBeExtracted($file)) {
+ $files[] = $this->toSplFileInfo($file);
+ }
+ }
+ } elseif (is_file($resource)) {
+ $files = $this->canBeExtracted($resource) ? [$this->toSplFileInfo($resource)] : [];
+ } else {
+ $files = $this->extractFromDirectory($resource);
+ }
+
+ return $files;
+ }
+
+ private function toSplFileInfo(string $file): \SplFileInfo
+ {
+ return new \SplFileInfo($file);
+ }
+
+ /**
+ * @return bool
+ *
+ * @throws InvalidArgumentException
+ */
+ protected function isFile(string $file)
+ {
+ if (!is_file($file)) {
+ throw new InvalidArgumentException(sprintf('The "%s" file does not exist.', $file));
+ }
+
+ return true;
+ }
+
+ /**
+ * @return bool
+ */
+ abstract protected function canBeExtracted(string $file);
+
+ /**
+ * @param string|array $resource Files, a file or a directory
+ *
+ * @return iterable files to be extracted
+ */
+ abstract protected function extractFromDirectory($resource);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/ChainExtractor.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/ChainExtractor.php
new file mode 100644
index 0000000..95dcf15
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/ChainExtractor.php
@@ -0,0 +1,57 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Extractor;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * ChainExtractor extracts translation messages from template files.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+class ChainExtractor implements ExtractorInterface
+{
+ /**
+ * The extractors.
+ *
+ * @var ExtractorInterface[]
+ */
+ private $extractors = [];
+
+ /**
+ * Adds a loader to the translation extractor.
+ */
+ public function addExtractor(string $format, ExtractorInterface $extractor)
+ {
+ $this->extractors[$format] = $extractor;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setPrefix(string $prefix)
+ {
+ foreach ($this->extractors as $extractor) {
+ $extractor->setPrefix($prefix);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function extract($directory, MessageCatalogue $catalogue)
+ {
+ foreach ($this->extractors as $extractor) {
+ $extractor->extract($directory, $catalogue);
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/ExtractorInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/ExtractorInterface.php
new file mode 100644
index 0000000..e1db8a9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/ExtractorInterface.php
@@ -0,0 +1,35 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Extractor;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * Extracts translation messages from a directory or files to the catalogue.
+ * New found messages are injected to the catalogue using the prefix.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+interface ExtractorInterface
+{
+ /**
+ * Extracts translation messages from files, a file or a directory to the catalogue.
+ *
+ * @param string|iterable<string> $resource Files, a file or a directory
+ */
+ public function extract($resource, MessageCatalogue $catalogue);
+
+ /**
+ * Sets the prefix that should be used for new found messages.
+ */
+ public function setPrefix(string $prefix);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/PhpExtractor.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/PhpExtractor.php
new file mode 100644
index 0000000..c5efb5f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/PhpExtractor.php
@@ -0,0 +1,336 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Extractor;
+
+use Symfony\Component\Finder\Finder;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * PhpExtractor extracts translation messages from a PHP template.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+class PhpExtractor extends AbstractFileExtractor implements ExtractorInterface
+{
+ public const MESSAGE_TOKEN = 300;
+ public const METHOD_ARGUMENTS_TOKEN = 1000;
+ public const DOMAIN_TOKEN = 1001;
+
+ /**
+ * Prefix for new found message.
+ *
+ * @var string
+ */
+ private $prefix = '';
+
+ /**
+ * The sequence that captures translation messages.
+ *
+ * @var array
+ */
+ protected $sequences = [
+ [
+ '->',
+ 'trans',
+ '(',
+ self::MESSAGE_TOKEN,
+ ',',
+ self::METHOD_ARGUMENTS_TOKEN,
+ ',',
+ self::DOMAIN_TOKEN,
+ ],
+ [
+ '->',
+ 'trans',
+ '(',
+ self::MESSAGE_TOKEN,
+ ],
+ [
+ 'new',
+ 'TranslatableMessage',
+ '(',
+ self::MESSAGE_TOKEN,
+ ',',
+ self::METHOD_ARGUMENTS_TOKEN,
+ ',',
+ self::DOMAIN_TOKEN,
+ ],
+ [
+ 'new',
+ 'TranslatableMessage',
+ '(',
+ self::MESSAGE_TOKEN,
+ ],
+ [
+ 'new',
+ '\\',
+ 'Symfony',
+ '\\',
+ 'Component',
+ '\\',
+ 'Translation',
+ '\\',
+ 'TranslatableMessage',
+ '(',
+ self::MESSAGE_TOKEN,
+ ',',
+ self::METHOD_ARGUMENTS_TOKEN,
+ ',',
+ self::DOMAIN_TOKEN,
+ ],
+ [
+ 'new',
+ '\Symfony\Component\Translation\TranslatableMessage',
+ '(',
+ self::MESSAGE_TOKEN,
+ ',',
+ self::METHOD_ARGUMENTS_TOKEN,
+ ',',
+ self::DOMAIN_TOKEN,
+ ],
+ [
+ 'new',
+ '\\',
+ 'Symfony',
+ '\\',
+ 'Component',
+ '\\',
+ 'Translation',
+ '\\',
+ 'TranslatableMessage',
+ '(',
+ self::MESSAGE_TOKEN,
+ ],
+ [
+ 'new',
+ '\Symfony\Component\Translation\TranslatableMessage',
+ '(',
+ self::MESSAGE_TOKEN,
+ ],
+ [
+ 't',
+ '(',
+ self::MESSAGE_TOKEN,
+ ',',
+ self::METHOD_ARGUMENTS_TOKEN,
+ ',',
+ self::DOMAIN_TOKEN,
+ ],
+ [
+ 't',
+ '(',
+ self::MESSAGE_TOKEN,
+ ],
+ ];
+
+ /**
+ * {@inheritdoc}
+ */
+ public function extract($resource, MessageCatalogue $catalog)
+ {
+ $files = $this->extractFiles($resource);
+ foreach ($files as $file) {
+ $this->parseTokens(token_get_all(file_get_contents($file)), $catalog, $file);
+
+ gc_mem_caches();
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setPrefix(string $prefix)
+ {
+ $this->prefix = $prefix;
+ }
+
+ /**
+ * Normalizes a token.
+ *
+ * @param mixed $token
+ *
+ * @return string|null
+ */
+ protected function normalizeToken($token)
+ {
+ if (isset($token[1]) && 'b"' !== $token) {
+ return $token[1];
+ }
+
+ return $token;
+ }
+
+ /**
+ * Seeks to a non-whitespace token.
+ */
+ private function seekToNextRelevantToken(\Iterator $tokenIterator)
+ {
+ for (; $tokenIterator->valid(); $tokenIterator->next()) {
+ $t = $tokenIterator->current();
+ if (\T_WHITESPACE !== $t[0]) {
+ break;
+ }
+ }
+ }
+
+ private function skipMethodArgument(\Iterator $tokenIterator)
+ {
+ $openBraces = 0;
+
+ for (; $tokenIterator->valid(); $tokenIterator->next()) {
+ $t = $tokenIterator->current();
+
+ if ('[' === $t[0] || '(' === $t[0]) {
+ ++$openBraces;
+ }
+
+ if (']' === $t[0] || ')' === $t[0]) {
+ --$openBraces;
+ }
+
+ if ((0 === $openBraces && ',' === $t[0]) || (-1 === $openBraces && ')' === $t[0])) {
+ break;
+ }
+ }
+ }
+
+ /**
+ * Extracts the message from the iterator while the tokens
+ * match allowed message tokens.
+ */
+ private function getValue(\Iterator $tokenIterator)
+ {
+ $message = '';
+ $docToken = '';
+ $docPart = '';
+
+ for (; $tokenIterator->valid(); $tokenIterator->next()) {
+ $t = $tokenIterator->current();
+ if ('.' === $t) {
+ // Concatenate with next token
+ continue;
+ }
+ if (!isset($t[1])) {
+ break;
+ }
+
+ switch ($t[0]) {
+ case \T_START_HEREDOC:
+ $docToken = $t[1];
+ break;
+ case \T_ENCAPSED_AND_WHITESPACE:
+ case \T_CONSTANT_ENCAPSED_STRING:
+ if ('' === $docToken) {
+ $message .= PhpStringTokenParser::parse($t[1]);
+ } else {
+ $docPart = $t[1];
+ }
+ break;
+ case \T_END_HEREDOC:
+ if ($indentation = strspn($t[1], ' ')) {
+ $docPartWithLineBreaks = $docPart;
+ $docPart = '';
+
+ foreach (preg_split('~(\r\n|\n|\r)~', $docPartWithLineBreaks, -1, \PREG_SPLIT_DELIM_CAPTURE) as $str) {
+ if (\in_array($str, ["\r\n", "\n", "\r"], true)) {
+ $docPart .= $str;
+ } else {
+ $docPart .= substr($str, $indentation);
+ }
+ }
+ }
+
+ $message .= PhpStringTokenParser::parseDocString($docToken, $docPart);
+ $docToken = '';
+ $docPart = '';
+ break;
+ case \T_WHITESPACE:
+ break;
+ default:
+ break 2;
+ }
+ }
+
+ return $message;
+ }
+
+ /**
+ * Extracts trans message from PHP tokens.
+ */
+ protected function parseTokens(array $tokens, MessageCatalogue $catalog, string $filename)
+ {
+ $tokenIterator = new \ArrayIterator($tokens);
+
+ for ($key = 0; $key < $tokenIterator->count(); ++$key) {
+ foreach ($this->sequences as $sequence) {
+ $message = '';
+ $domain = 'messages';
+ $tokenIterator->seek($key);
+
+ foreach ($sequence as $sequenceKey => $item) {
+ $this->seekToNextRelevantToken($tokenIterator);
+
+ if ($this->normalizeToken($tokenIterator->current()) === $item) {
+ $tokenIterator->next();
+ continue;
+ } elseif (self::MESSAGE_TOKEN === $item) {
+ $message = $this->getValue($tokenIterator);
+
+ if (\count($sequence) === ($sequenceKey + 1)) {
+ break;
+ }
+ } elseif (self::METHOD_ARGUMENTS_TOKEN === $item) {
+ $this->skipMethodArgument($tokenIterator);
+ } elseif (self::DOMAIN_TOKEN === $item) {
+ $domainToken = $this->getValue($tokenIterator);
+ if ('' !== $domainToken) {
+ $domain = $domainToken;
+ }
+
+ break;
+ } else {
+ break;
+ }
+ }
+
+ if ($message) {
+ $catalog->set($message, $this->prefix.$message, $domain);
+ $metadata = $catalog->getMetadata($message, $domain) ?? [];
+ $normalizedFilename = preg_replace('{[\\\\/]+}', '/', $filename);
+ $metadata['sources'][] = $normalizedFilename.':'.$tokens[$key][2];
+ $catalog->setMetadata($message, $metadata, $domain);
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * @return bool
+ *
+ * @throws \InvalidArgumentException
+ */
+ protected function canBeExtracted(string $file)
+ {
+ return $this->isFile($file) && 'php' === pathinfo($file, \PATHINFO_EXTENSION);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function extractFromDirectory($directory)
+ {
+ $finder = new Finder();
+
+ return $finder->files()->name('*.php')->in($directory);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/PhpStringTokenParser.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/PhpStringTokenParser.php
new file mode 100644
index 0000000..1d82caf
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Extractor/PhpStringTokenParser.php
@@ -0,0 +1,142 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Extractor;
+
+/*
+ * The following is derived from code at http://github.com/nikic/PHP-Parser
+ *
+ * Copyright (c) 2011 by Nikita Popov
+ *
+ * Some rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * * The names of the contributors may not be used to endorse or
+ * promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+class PhpStringTokenParser
+{
+ protected static $replacements = [
+ '\\' => '\\',
+ '$' => '$',
+ 'n' => "\n",
+ 'r' => "\r",
+ 't' => "\t",
+ 'f' => "\f",
+ 'v' => "\v",
+ 'e' => "\x1B",
+ ];
+
+ /**
+ * Parses a string token.
+ *
+ * @param string $str String token content
+ *
+ * @return string The parsed string
+ */
+ public static function parse(string $str)
+ {
+ $bLength = 0;
+ if ('b' === $str[0]) {
+ $bLength = 1;
+ }
+
+ if ('\'' === $str[$bLength]) {
+ return str_replace(
+ ['\\\\', '\\\''],
+ ['\\', '\''],
+ substr($str, $bLength + 1, -1)
+ );
+ } else {
+ return self::parseEscapeSequences(substr($str, $bLength + 1, -1), '"');
+ }
+ }
+
+ /**
+ * Parses escape sequences in strings (all string types apart from single quoted).
+ *
+ * @param string $str String without quotes
+ * @param string|null $quote Quote type
+ *
+ * @return string String with escape sequences parsed
+ */
+ public static function parseEscapeSequences(string $str, string $quote = null)
+ {
+ if (null !== $quote) {
+ $str = str_replace('\\'.$quote, $quote, $str);
+ }
+
+ return preg_replace_callback(
+ '~\\\\([\\\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3})~',
+ [__CLASS__, 'parseCallback'],
+ $str
+ );
+ }
+
+ private static function parseCallback(array $matches): string
+ {
+ $str = $matches[1];
+
+ if (isset(self::$replacements[$str])) {
+ return self::$replacements[$str];
+ } elseif ('x' === $str[0] || 'X' === $str[0]) {
+ return \chr(hexdec($str));
+ } else {
+ return \chr(octdec($str));
+ }
+ }
+
+ /**
+ * Parses a constant doc string.
+ *
+ * @param string $startToken Doc string start token content (<<<SMTHG)
+ * @param string $str String token content
+ *
+ * @return string Parsed string
+ */
+ public static function parseDocString(string $startToken, string $str)
+ {
+ // strip last newline (thanks tokenizer for sticking it into the string!)
+ $str = preg_replace('~(\r\n|\n|\r)$~', '', $str);
+
+ // nowdoc string
+ if (str_contains($startToken, '\'')) {
+ return $str;
+ }
+
+ return self::parseEscapeSequences($str, null);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Formatter/IntlFormatter.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Formatter/IntlFormatter.php
new file mode 100644
index 0000000..f7f1c36
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Formatter/IntlFormatter.php
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Formatter;
+
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\Exception\LogicException;
+
+/**
+ * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+class IntlFormatter implements IntlFormatterInterface
+{
+ private $hasMessageFormatter;
+ private $cache = [];
+
+ /**
+ * {@inheritdoc}
+ */
+ public function formatIntl(string $message, string $locale, array $parameters = []): string
+ {
+ // MessageFormatter constructor throws an exception if the message is empty
+ if ('' === $message) {
+ return '';
+ }
+
+ if (!$formatter = $this->cache[$locale][$message] ?? null) {
+ if (!($this->hasMessageFormatter ?? $this->hasMessageFormatter = class_exists(\MessageFormatter::class))) {
+ throw new LogicException('Cannot parse message translation: please install the "intl" PHP extension or the "symfony/polyfill-intl-messageformatter" package.');
+ }
+ try {
+ $this->cache[$locale][$message] = $formatter = new \MessageFormatter($locale, $message);
+ } catch (\IntlException $e) {
+ throw new InvalidArgumentException(sprintf('Invalid message format (error #%d): ', intl_get_error_code()).intl_get_error_message(), 0, $e);
+ }
+ }
+
+ foreach ($parameters as $key => $value) {
+ if (\in_array($key[0] ?? null, ['%', '{'], true)) {
+ unset($parameters[$key]);
+ $parameters[trim($key, '%{ }')] = $value;
+ }
+ }
+
+ if (false === $message = $formatter->format($parameters)) {
+ throw new InvalidArgumentException(sprintf('Unable to format message (error #%s): ', $formatter->getErrorCode()).$formatter->getErrorMessage());
+ }
+
+ return $message;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Formatter/IntlFormatterInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Formatter/IntlFormatterInterface.php
new file mode 100644
index 0000000..02fc6ac
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Formatter/IntlFormatterInterface.php
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Formatter;
+
+/**
+ * Formats ICU message patterns.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+interface IntlFormatterInterface
+{
+ /**
+ * Formats a localized message using rules defined by ICU MessageFormat.
+ *
+ * @see http://icu-project.org/apiref/icu4c/classMessageFormat.html#details
+ */
+ public function formatIntl(string $message, string $locale, array $parameters = []): string;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Formatter/MessageFormatter.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Formatter/MessageFormatter.php
new file mode 100644
index 0000000..0407964
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Formatter/MessageFormatter.php
@@ -0,0 +1,56 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Formatter;
+
+use Symfony\Component\Translation\IdentityTranslator;
+use Symfony\Contracts\Translation\TranslatorInterface;
+
+// Help opcache.preload discover always-needed symbols
+class_exists(IntlFormatter::class);
+
+/**
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+class MessageFormatter implements MessageFormatterInterface, IntlFormatterInterface
+{
+ private $translator;
+ private $intlFormatter;
+
+ /**
+ * @param TranslatorInterface|null $translator An identity translator to use as selector for pluralization
+ */
+ public function __construct(TranslatorInterface $translator = null, IntlFormatterInterface $intlFormatter = null)
+ {
+ $this->translator = $translator ?? new IdentityTranslator();
+ $this->intlFormatter = $intlFormatter ?? new IntlFormatter();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function format(string $message, string $locale, array $parameters = [])
+ {
+ if ($this->translator instanceof TranslatorInterface) {
+ return $this->translator->trans($message, $parameters, null, $locale);
+ }
+
+ return strtr($message, $parameters);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function formatIntl(string $message, string $locale, array $parameters = []): string
+ {
+ return $this->intlFormatter->formatIntl($message, $locale, $parameters);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Formatter/MessageFormatterInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Formatter/MessageFormatterInterface.php
new file mode 100644
index 0000000..b85dbfd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Formatter/MessageFormatterInterface.php
@@ -0,0 +1,30 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Formatter;
+
+/**
+ * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+interface MessageFormatterInterface
+{
+ /**
+ * Formats a localized message pattern with given arguments.
+ *
+ * @param string $message The message (may also be an object that can be cast to string)
+ * @param string $locale The message locale
+ * @param array $parameters An array of parameters for the message
+ *
+ * @return string
+ */
+ public function format(string $message, string $locale, array $parameters = []);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/IdentityTranslator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/IdentityTranslator.php
new file mode 100644
index 0000000..46875ed
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/IdentityTranslator.php
@@ -0,0 +1,26 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+use Symfony\Contracts\Translation\LocaleAwareInterface;
+use Symfony\Contracts\Translation\TranslatorInterface;
+use Symfony\Contracts\Translation\TranslatorTrait;
+
+/**
+ * IdentityTranslator does not translate anything.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class IdentityTranslator implements TranslatorInterface, LocaleAwareInterface
+{
+ use TranslatorTrait;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/LICENSE b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/LICENSE
new file mode 100644
index 0000000..9ff2d0d
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2004-2021 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/ArrayLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/ArrayLoader.php
new file mode 100644
index 0000000..0758da8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/ArrayLoader.php
@@ -0,0 +1,58 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * ArrayLoader loads translations from a PHP array.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ArrayLoader implements LoaderInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, string $locale, string $domain = 'messages')
+ {
+ $resource = $this->flatten($resource);
+ $catalogue = new MessageCatalogue($locale);
+ $catalogue->add($resource, $domain);
+
+ return $catalogue;
+ }
+
+ /**
+ * Flattens an nested array of translations.
+ *
+ * The scheme used is:
+ * 'key' => ['key2' => ['key3' => 'value']]
+ * Becomes:
+ * 'key.key2.key3' => 'value'
+ */
+ private function flatten(array $messages): array
+ {
+ $result = [];
+ foreach ($messages as $key => $value) {
+ if (\is_array($value)) {
+ foreach ($this->flatten($value) as $k => $v) {
+ $result[$key.'.'.$k] = $v;
+ }
+ } else {
+ $result[$key] = $value;
+ }
+ }
+
+ return $result;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/CsvFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/CsvFileLoader.php
new file mode 100644
index 0000000..8d5d4db
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/CsvFileLoader.php
@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+
+/**
+ * CsvFileLoader loads translations from CSV files.
+ *
+ * @author Saša Stamenković <umpirsky@gmail.com>
+ */
+class CsvFileLoader extends FileLoader
+{
+ private $delimiter = ';';
+ private $enclosure = '"';
+ private $escape = '\\';
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function loadResource(string $resource)
+ {
+ $messages = [];
+
+ try {
+ $file = new \SplFileObject($resource, 'rb');
+ } catch (\RuntimeException $e) {
+ throw new NotFoundResourceException(sprintf('Error opening file "%s".', $resource), 0, $e);
+ }
+
+ $file->setFlags(\SplFileObject::READ_CSV | \SplFileObject::SKIP_EMPTY);
+ $file->setCsvControl($this->delimiter, $this->enclosure, $this->escape);
+
+ foreach ($file as $data) {
+ if (false === $data) {
+ continue;
+ }
+
+ if ('#' !== substr($data[0], 0, 1) && isset($data[1]) && 2 === \count($data)) {
+ $messages[$data[0]] = $data[1];
+ }
+ }
+
+ return $messages;
+ }
+
+ /**
+ * Sets the delimiter, enclosure, and escape character for CSV.
+ */
+ public function setCsvControl(string $delimiter = ';', string $enclosure = '"', string $escape = '\\')
+ {
+ $this->delimiter = $delimiter;
+ $this->enclosure = $enclosure;
+ $this->escape = $escape;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/FileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/FileLoader.php
new file mode 100644
index 0000000..4725ea6
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/FileLoader.php
@@ -0,0 +1,63 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Config\Resource\FileResource;
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+
+/**
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+abstract class FileLoader extends ArrayLoader
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, string $locale, string $domain = 'messages')
+ {
+ if (!stream_is_local($resource)) {
+ throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ }
+
+ if (!file_exists($resource)) {
+ throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ }
+
+ $messages = $this->loadResource($resource);
+
+ // empty resource
+ if (null === $messages) {
+ $messages = [];
+ }
+
+ // not an array
+ if (!\is_array($messages)) {
+ throw new InvalidResourceException(sprintf('Unable to load file "%s".', $resource));
+ }
+
+ $catalogue = parent::load($messages, $locale, $domain);
+
+ if (class_exists(FileResource::class)) {
+ $catalogue->addResource(new FileResource($resource));
+ }
+
+ return $catalogue;
+ }
+
+ /**
+ * @return array
+ *
+ * @throws InvalidResourceException if stream content has an invalid format
+ */
+ abstract protected function loadResource(string $resource);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IcuDatFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IcuDatFileLoader.php
new file mode 100644
index 0000000..2a1aecc
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IcuDatFileLoader.php
@@ -0,0 +1,61 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Config\Resource\FileResource;
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * IcuResFileLoader loads translations from a resource bundle.
+ *
+ * @author stealth35
+ */
+class IcuDatFileLoader extends IcuResFileLoader
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, string $locale, string $domain = 'messages')
+ {
+ if (!stream_is_local($resource.'.dat')) {
+ throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ }
+
+ if (!file_exists($resource.'.dat')) {
+ throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ }
+
+ try {
+ $rb = new \ResourceBundle($locale, $resource);
+ } catch (\Exception $e) {
+ $rb = null;
+ }
+
+ if (!$rb) {
+ throw new InvalidResourceException(sprintf('Cannot load resource "%s".', $resource));
+ } elseif (intl_is_failure($rb->getErrorCode())) {
+ throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode());
+ }
+
+ $messages = $this->flatten($rb);
+ $catalogue = new MessageCatalogue($locale);
+ $catalogue->add($messages, $domain);
+
+ if (class_exists(FileResource::class)) {
+ $catalogue->addResource(new FileResource($resource.'.dat'));
+ }
+
+ return $catalogue;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IcuResFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IcuResFileLoader.php
new file mode 100644
index 0000000..64bbd3e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IcuResFileLoader.php
@@ -0,0 +1,91 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Config\Resource\DirectoryResource;
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * IcuResFileLoader loads translations from a resource bundle.
+ *
+ * @author stealth35
+ */
+class IcuResFileLoader implements LoaderInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, string $locale, string $domain = 'messages')
+ {
+ if (!stream_is_local($resource)) {
+ throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ }
+
+ if (!is_dir($resource)) {
+ throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ }
+
+ try {
+ $rb = new \ResourceBundle($locale, $resource);
+ } catch (\Exception $e) {
+ $rb = null;
+ }
+
+ if (!$rb) {
+ throw new InvalidResourceException(sprintf('Cannot load resource "%s".', $resource));
+ } elseif (intl_is_failure($rb->getErrorCode())) {
+ throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode());
+ }
+
+ $messages = $this->flatten($rb);
+ $catalogue = new MessageCatalogue($locale);
+ $catalogue->add($messages, $domain);
+
+ if (class_exists(DirectoryResource::class)) {
+ $catalogue->addResource(new DirectoryResource($resource));
+ }
+
+ return $catalogue;
+ }
+
+ /**
+ * Flattens an ResourceBundle.
+ *
+ * The scheme used is:
+ * key { key2 { key3 { "value" } } }
+ * Becomes:
+ * 'key.key2.key3' => 'value'
+ *
+ * This function takes an array by reference and will modify it
+ *
+ * @param \ResourceBundle $rb The ResourceBundle that will be flattened
+ * @param array $messages Used internally for recursive calls
+ * @param string $path Current path being parsed, used internally for recursive calls
+ *
+ * @return array the flattened ResourceBundle
+ */
+ protected function flatten(\ResourceBundle $rb, array &$messages = [], string $path = null)
+ {
+ foreach ($rb as $key => $value) {
+ $nodePath = $path ? $path.'.'.$key : $key;
+ if ($value instanceof \ResourceBundle) {
+ $this->flatten($value, $messages, $nodePath);
+ } else {
+ $messages[$nodePath] = $value;
+ }
+ }
+
+ return $messages;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IniFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IniFileLoader.php
new file mode 100644
index 0000000..7398f77
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/IniFileLoader.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+/**
+ * IniFileLoader loads translations from an ini file.
+ *
+ * @author stealth35
+ */
+class IniFileLoader extends FileLoader
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function loadResource(string $resource)
+ {
+ return parse_ini_file($resource, true);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/JsonFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/JsonFileLoader.php
new file mode 100644
index 0000000..5aefba0
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/JsonFileLoader.php
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+
+/**
+ * JsonFileLoader loads translations from an json file.
+ *
+ * @author singles
+ */
+class JsonFileLoader extends FileLoader
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function loadResource(string $resource)
+ {
+ $messages = [];
+ if ($data = file_get_contents($resource)) {
+ $messages = json_decode($data, true);
+
+ if (0 < $errorCode = json_last_error()) {
+ throw new InvalidResourceException('Error parsing JSON: '.$this->getJSONErrorMessage($errorCode));
+ }
+ }
+
+ return $messages;
+ }
+
+ /**
+ * Translates JSON_ERROR_* constant into meaningful message.
+ */
+ private function getJSONErrorMessage(int $errorCode): string
+ {
+ switch ($errorCode) {
+ case \JSON_ERROR_DEPTH:
+ return 'Maximum stack depth exceeded';
+ case \JSON_ERROR_STATE_MISMATCH:
+ return 'Underflow or the modes mismatch';
+ case \JSON_ERROR_CTRL_CHAR:
+ return 'Unexpected control character found';
+ case \JSON_ERROR_SYNTAX:
+ return 'Syntax error, malformed JSON';
+ case \JSON_ERROR_UTF8:
+ return 'Malformed UTF-8 characters, possibly incorrectly encoded';
+ default:
+ return 'Unknown error';
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/LoaderInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/LoaderInterface.php
new file mode 100644
index 0000000..2073f2b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/LoaderInterface.php
@@ -0,0 +1,38 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * LoaderInterface is the interface implemented by all translation loaders.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface LoaderInterface
+{
+ /**
+ * Loads a locale.
+ *
+ * @param mixed $resource A resource
+ * @param string $locale A locale
+ * @param string $domain The domain
+ *
+ * @return MessageCatalogue A MessageCatalogue instance
+ *
+ * @throws NotFoundResourceException when the resource cannot be found
+ * @throws InvalidResourceException when the resource cannot be loaded
+ */
+ public function load($resource, string $locale, string $domain = 'messages');
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/MoFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/MoFileLoader.php
new file mode 100644
index 0000000..0ff6549
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/MoFileLoader.php
@@ -0,0 +1,140 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+
+/**
+ * @copyright Copyright (c) 2010, Union of RAD http://union-of-rad.org (http://lithify.me/)
+ */
+class MoFileLoader extends FileLoader
+{
+ /**
+ * Magic used for validating the format of an MO file as well as
+ * detecting if the machine used to create that file was little endian.
+ */
+ public const MO_LITTLE_ENDIAN_MAGIC = 0x950412de;
+
+ /**
+ * Magic used for validating the format of an MO file as well as
+ * detecting if the machine used to create that file was big endian.
+ */
+ public const MO_BIG_ENDIAN_MAGIC = 0xde120495;
+
+ /**
+ * The size of the header of an MO file in bytes.
+ */
+ public const MO_HEADER_SIZE = 28;
+
+ /**
+ * Parses machine object (MO) format, independent of the machine's endian it
+ * was created on. Both 32bit and 64bit systems are supported.
+ *
+ * {@inheritdoc}
+ */
+ protected function loadResource(string $resource)
+ {
+ $stream = fopen($resource, 'r');
+
+ $stat = fstat($stream);
+
+ if ($stat['size'] < self::MO_HEADER_SIZE) {
+ throw new InvalidResourceException('MO stream content has an invalid format.');
+ }
+ $magic = unpack('V1', fread($stream, 4));
+ $magic = hexdec(substr(dechex(current($magic)), -8));
+
+ if (self::MO_LITTLE_ENDIAN_MAGIC == $magic) {
+ $isBigEndian = false;
+ } elseif (self::MO_BIG_ENDIAN_MAGIC == $magic) {
+ $isBigEndian = true;
+ } else {
+ throw new InvalidResourceException('MO stream content has an invalid format.');
+ }
+
+ // formatRevision
+ $this->readLong($stream, $isBigEndian);
+ $count = $this->readLong($stream, $isBigEndian);
+ $offsetId = $this->readLong($stream, $isBigEndian);
+ $offsetTranslated = $this->readLong($stream, $isBigEndian);
+ // sizeHashes
+ $this->readLong($stream, $isBigEndian);
+ // offsetHashes
+ $this->readLong($stream, $isBigEndian);
+
+ $messages = [];
+
+ for ($i = 0; $i < $count; ++$i) {
+ $pluralId = null;
+ $translated = null;
+
+ fseek($stream, $offsetId + $i * 8);
+
+ $length = $this->readLong($stream, $isBigEndian);
+ $offset = $this->readLong($stream, $isBigEndian);
+
+ if ($length < 1) {
+ continue;
+ }
+
+ fseek($stream, $offset);
+ $singularId = fread($stream, $length);
+
+ if (str_contains($singularId, "\000")) {
+ [$singularId, $pluralId] = explode("\000", $singularId);
+ }
+
+ fseek($stream, $offsetTranslated + $i * 8);
+ $length = $this->readLong($stream, $isBigEndian);
+ $offset = $this->readLong($stream, $isBigEndian);
+
+ if ($length < 1) {
+ continue;
+ }
+
+ fseek($stream, $offset);
+ $translated = fread($stream, $length);
+
+ if (str_contains($translated, "\000")) {
+ $translated = explode("\000", $translated);
+ }
+
+ $ids = ['singular' => $singularId, 'plural' => $pluralId];
+ $item = compact('ids', 'translated');
+
+ if (!empty($item['ids']['singular'])) {
+ $id = $item['ids']['singular'];
+ if (isset($item['ids']['plural'])) {
+ $id .= '|'.$item['ids']['plural'];
+ }
+ $messages[$id] = stripcslashes(implode('|', (array) $item['translated']));
+ }
+ }
+
+ fclose($stream);
+
+ return array_filter($messages);
+ }
+
+ /**
+ * Reads an unsigned long from stream respecting endianness.
+ *
+ * @param resource $stream
+ */
+ private function readLong($stream, bool $isBigEndian): int
+ {
+ $result = unpack($isBigEndian ? 'N1' : 'V1', fread($stream, 4));
+ $result = current($result);
+
+ return (int) substr($result, -8);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/PhpFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/PhpFileLoader.php
new file mode 100644
index 0000000..85f1090
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/PhpFileLoader.php
@@ -0,0 +1,42 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+/**
+ * PhpFileLoader loads translations from PHP files returning an array of translations.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class PhpFileLoader extends FileLoader
+{
+ private static $cache = [];
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function loadResource(string $resource)
+ {
+ if ([] === self::$cache && \function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) || filter_var(ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOLEAN))) {
+ self::$cache = null;
+ }
+
+ if (null === self::$cache) {
+ return require $resource;
+ }
+
+ if (isset(self::$cache[$resource])) {
+ return self::$cache[$resource];
+ }
+
+ return self::$cache[$resource] = require $resource;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/PoFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/PoFileLoader.php
new file mode 100644
index 0000000..ee143e2
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/PoFileLoader.php
@@ -0,0 +1,149 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+/**
+ * @copyright Copyright (c) 2010, Union of RAD https://github.com/UnionOfRAD/lithium
+ * @copyright Copyright (c) 2012, Clemens Tolboom
+ */
+class PoFileLoader extends FileLoader
+{
+ /**
+ * Parses portable object (PO) format.
+ *
+ * From https://www.gnu.org/software/gettext/manual/gettext.html#PO-Files
+ * we should be able to parse files having:
+ *
+ * white-space
+ * # translator-comments
+ * #. extracted-comments
+ * #: reference...
+ * #, flag...
+ * #| msgid previous-untranslated-string
+ * msgid untranslated-string
+ * msgstr translated-string
+ *
+ * extra or different lines are:
+ *
+ * #| msgctxt previous-context
+ * #| msgid previous-untranslated-string
+ * msgctxt context
+ *
+ * #| msgid previous-untranslated-string-singular
+ * #| msgid_plural previous-untranslated-string-plural
+ * msgid untranslated-string-singular
+ * msgid_plural untranslated-string-plural
+ * msgstr[0] translated-string-case-0
+ * ...
+ * msgstr[N] translated-string-case-n
+ *
+ * The definition states:
+ * - white-space and comments are optional.
+ * - msgid "" that an empty singleline defines a header.
+ *
+ * This parser sacrifices some features of the reference implementation the
+ * differences to that implementation are as follows.
+ * - No support for comments spanning multiple lines.
+ * - Translator and extracted comments are treated as being the same type.
+ * - Message IDs are allowed to have other encodings as just US-ASCII.
+ *
+ * Items with an empty id are ignored.
+ *
+ * {@inheritdoc}
+ */
+ protected function loadResource(string $resource)
+ {
+ $stream = fopen($resource, 'r');
+
+ $defaults = [
+ 'ids' => [],
+ 'translated' => null,
+ ];
+
+ $messages = [];
+ $item = $defaults;
+ $flags = [];
+
+ while ($line = fgets($stream)) {
+ $line = trim($line);
+
+ if ('' === $line) {
+ // Whitespace indicated current item is done
+ if (!\in_array('fuzzy', $flags)) {
+ $this->addMessage($messages, $item);
+ }
+ $item = $defaults;
+ $flags = [];
+ } elseif ('#,' === substr($line, 0, 2)) {
+ $flags = array_map('trim', explode(',', substr($line, 2)));
+ } elseif ('msgid "' === substr($line, 0, 7)) {
+ // We start a new msg so save previous
+ // TODO: this fails when comments or contexts are added
+ $this->addMessage($messages, $item);
+ $item = $defaults;
+ $item['ids']['singular'] = substr($line, 7, -1);
+ } elseif ('msgstr "' === substr($line, 0, 8)) {
+ $item['translated'] = substr($line, 8, -1);
+ } elseif ('"' === $line[0]) {
+ $continues = isset($item['translated']) ? 'translated' : 'ids';
+
+ if (\is_array($item[$continues])) {
+ end($item[$continues]);
+ $item[$continues][key($item[$continues])] .= substr($line, 1, -1);
+ } else {
+ $item[$continues] .= substr($line, 1, -1);
+ }
+ } elseif ('msgid_plural "' === substr($line, 0, 14)) {
+ $item['ids']['plural'] = substr($line, 14, -1);
+ } elseif ('msgstr[' === substr($line, 0, 7)) {
+ $size = strpos($line, ']');
+ $item['translated'][(int) substr($line, 7, 1)] = substr($line, $size + 3, -1);
+ }
+ }
+ // save last item
+ if (!\in_array('fuzzy', $flags)) {
+ $this->addMessage($messages, $item);
+ }
+ fclose($stream);
+
+ return $messages;
+ }
+
+ /**
+ * Save a translation item to the messages.
+ *
+ * A .po file could contain by error missing plural indexes. We need to
+ * fix these before saving them.
+ */
+ private function addMessage(array &$messages, array $item)
+ {
+ if (!empty($item['ids']['singular'])) {
+ $id = stripcslashes($item['ids']['singular']);
+ if (isset($item['ids']['plural'])) {
+ $id .= '|'.stripcslashes($item['ids']['plural']);
+ }
+
+ $translated = (array) $item['translated'];
+ // PO are by definition indexed so sort by index.
+ ksort($translated);
+ // Make sure every index is filled.
+ end($translated);
+ $count = key($translated);
+ // Fill missing spots with '-'.
+ $empties = array_fill(0, $count + 1, '-');
+ $translated += $empties;
+ ksort($translated);
+
+ $messages[$id] = stripcslashes(implode('|', $translated));
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/QtFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/QtFileLoader.php
new file mode 100644
index 0000000..9cf2fe9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/QtFileLoader.php
@@ -0,0 +1,82 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Config\Resource\FileResource;
+use Symfony\Component\Config\Util\XmlUtils;
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+use Symfony\Component\Translation\Exception\RuntimeException;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * QtFileLoader loads translations from QT Translations XML files.
+ *
+ * @author Benjamin Eberlei <kontakt@beberlei.de>
+ */
+class QtFileLoader implements LoaderInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, string $locale, string $domain = 'messages')
+ {
+ if (!class_exists(XmlUtils::class)) {
+ throw new RuntimeException('Loading translations from the QT format requires the Symfony Config component.');
+ }
+
+ if (!stream_is_local($resource)) {
+ throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ }
+
+ if (!file_exists($resource)) {
+ throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ }
+
+ try {
+ $dom = XmlUtils::loadFile($resource);
+ } catch (\InvalidArgumentException $e) {
+ throw new InvalidResourceException(sprintf('Unable to load "%s".', $resource), $e->getCode(), $e);
+ }
+
+ $internalErrors = libxml_use_internal_errors(true);
+ libxml_clear_errors();
+
+ $xpath = new \DOMXPath($dom);
+ $nodes = $xpath->evaluate('//TS/context/name[text()="'.$domain.'"]');
+
+ $catalogue = new MessageCatalogue($locale);
+ if (1 == $nodes->length) {
+ $translations = $nodes->item(0)->nextSibling->parentNode->parentNode->getElementsByTagName('message');
+ foreach ($translations as $translation) {
+ $translationValue = (string) $translation->getElementsByTagName('translation')->item(0)->nodeValue;
+
+ if (!empty($translationValue)) {
+ $catalogue->set(
+ (string) $translation->getElementsByTagName('source')->item(0)->nodeValue,
+ $translationValue,
+ $domain
+ );
+ }
+ $translation = $translation->nextSibling;
+ }
+
+ if (class_exists(FileResource::class)) {
+ $catalogue->addResource(new FileResource($resource));
+ }
+ }
+
+ libxml_use_internal_errors($internalErrors);
+
+ return $catalogue;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/XliffFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/XliffFileLoader.php
new file mode 100644
index 0000000..35ad33e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/XliffFileLoader.php
@@ -0,0 +1,232 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Config\Resource\FileResource;
+use Symfony\Component\Config\Util\Exception\InvalidXmlException;
+use Symfony\Component\Config\Util\Exception\XmlParsingException;
+use Symfony\Component\Config\Util\XmlUtils;
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+use Symfony\Component\Translation\Exception\RuntimeException;
+use Symfony\Component\Translation\MessageCatalogue;
+use Symfony\Component\Translation\Util\XliffUtils;
+
+/**
+ * XliffFileLoader loads translations from XLIFF files.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class XliffFileLoader implements LoaderInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function load($resource, string $locale, string $domain = 'messages')
+ {
+ if (!class_exists(XmlUtils::class)) {
+ throw new RuntimeException('Loading translations from the Xliff format requires the Symfony Config component.');
+ }
+
+ if (!$this->isXmlString($resource)) {
+ if (!stream_is_local($resource)) {
+ throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
+ }
+
+ if (!file_exists($resource)) {
+ throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
+ }
+
+ if (!is_file($resource)) {
+ throw new InvalidResourceException(sprintf('This is neither a file nor an XLIFF string "%s".', $resource));
+ }
+ }
+
+ try {
+ if ($this->isXmlString($resource)) {
+ $dom = XmlUtils::parse($resource);
+ } else {
+ $dom = XmlUtils::loadFile($resource);
+ }
+ } catch (\InvalidArgumentException | XmlParsingException | InvalidXmlException $e) {
+ throw new InvalidResourceException(sprintf('Unable to load "%s": ', $resource).$e->getMessage(), $e->getCode(), $e);
+ }
+
+ if ($errors = XliffUtils::validateSchema($dom)) {
+ throw new InvalidResourceException(sprintf('Invalid resource provided: "%s"; Errors: ', $resource).XliffUtils::getErrorsAsString($errors));
+ }
+
+ $catalogue = new MessageCatalogue($locale);
+ $this->extract($dom, $catalogue, $domain);
+
+ if (is_file($resource) && class_exists(FileResource::class)) {
+ $catalogue->addResource(new FileResource($resource));
+ }
+
+ return $catalogue;
+ }
+
+ private function extract(\DOMDocument $dom, MessageCatalogue $catalogue, string $domain)
+ {
+ $xliffVersion = XliffUtils::getVersionNumber($dom);
+
+ if ('1.2' === $xliffVersion) {
+ $this->extractXliff1($dom, $catalogue, $domain);
+ }
+
+ if ('2.0' === $xliffVersion) {
+ $this->extractXliff2($dom, $catalogue, $domain);
+ }
+ }
+
+ /**
+ * Extract messages and metadata from DOMDocument into a MessageCatalogue.
+ */
+ private function extractXliff1(\DOMDocument $dom, MessageCatalogue $catalogue, string $domain)
+ {
+ $xml = simplexml_import_dom($dom);
+ $encoding = $dom->encoding ? strtoupper($dom->encoding) : null;
+
+ $namespace = 'urn:oasis:names:tc:xliff:document:1.2';
+ $xml->registerXPathNamespace('xliff', $namespace);
+
+ foreach ($xml->xpath('//xliff:file') as $file) {
+ $fileAttributes = $file->attributes();
+
+ $file->registerXPathNamespace('xliff', $namespace);
+
+ foreach ($file->xpath('.//xliff:trans-unit') as $translation) {
+ $attributes = $translation->attributes();
+
+ if (!(isset($attributes['resname']) || isset($translation->source))) {
+ continue;
+ }
+
+ $source = isset($attributes['resname']) && $attributes['resname'] ? $attributes['resname'] : $translation->source;
+ // If the xlf file has another encoding specified, try to convert it because
+ // simple_xml will always return utf-8 encoded values
+ $target = $this->utf8ToCharset((string) ($translation->target ?? $translation->source), $encoding);
+
+ $catalogue->set((string) $source, $target, $domain);
+
+ $metadata = [
+ 'source' => (string) $translation->source,
+ 'file' => [
+ 'original' => (string) $fileAttributes['original'],
+ ],
+ ];
+ if ($notes = $this->parseNotesMetadata($translation->note, $encoding)) {
+ $metadata['notes'] = $notes;
+ }
+
+ if (isset($translation->target) && $translation->target->attributes()) {
+ $metadata['target-attributes'] = [];
+ foreach ($translation->target->attributes() as $key => $value) {
+ $metadata['target-attributes'][$key] = (string) $value;
+ }
+ }
+
+ if (isset($attributes['id'])) {
+ $metadata['id'] = (string) $attributes['id'];
+ }
+
+ $catalogue->setMetadata((string) $source, $metadata, $domain);
+ }
+ }
+ }
+
+ private function extractXliff2(\DOMDocument $dom, MessageCatalogue $catalogue, string $domain)
+ {
+ $xml = simplexml_import_dom($dom);
+ $encoding = $dom->encoding ? strtoupper($dom->encoding) : null;
+
+ $xml->registerXPathNamespace('xliff', 'urn:oasis:names:tc:xliff:document:2.0');
+
+ foreach ($xml->xpath('//xliff:unit') as $unit) {
+ foreach ($unit->segment as $segment) {
+ $attributes = $unit->attributes();
+ $source = $attributes['name'] ?? $segment->source;
+
+ // If the xlf file has another encoding specified, try to convert it because
+ // simple_xml will always return utf-8 encoded values
+ $target = $this->utf8ToCharset((string) ($segment->target ?? $segment->source), $encoding);
+
+ $catalogue->set((string) $source, $target, $domain);
+
+ $metadata = [];
+ if (isset($segment->target) && $segment->target->attributes()) {
+ $metadata['target-attributes'] = [];
+ foreach ($segment->target->attributes() as $key => $value) {
+ $metadata['target-attributes'][$key] = (string) $value;
+ }
+ }
+
+ if (isset($unit->notes)) {
+ $metadata['notes'] = [];
+ foreach ($unit->notes->note as $noteNode) {
+ $note = [];
+ foreach ($noteNode->attributes() as $key => $value) {
+ $note[$key] = (string) $value;
+ }
+ $note['content'] = (string) $noteNode;
+ $metadata['notes'][] = $note;
+ }
+ }
+
+ $catalogue->setMetadata((string) $source, $metadata, $domain);
+ }
+ }
+ }
+
+ /**
+ * Convert a UTF8 string to the specified encoding.
+ */
+ private function utf8ToCharset(string $content, string $encoding = null): string
+ {
+ if ('UTF-8' !== $encoding && !empty($encoding)) {
+ return mb_convert_encoding($content, $encoding, 'UTF-8');
+ }
+
+ return $content;
+ }
+
+ private function parseNotesMetadata(\SimpleXMLElement $noteElement = null, string $encoding = null): array
+ {
+ $notes = [];
+
+ if (null === $noteElement) {
+ return $notes;
+ }
+
+ /** @var \SimpleXMLElement $xmlNote */
+ foreach ($noteElement as $xmlNote) {
+ $noteAttributes = $xmlNote->attributes();
+ $note = ['content' => $this->utf8ToCharset((string) $xmlNote, $encoding)];
+ if (isset($noteAttributes['priority'])) {
+ $note['priority'] = (int) $noteAttributes['priority'];
+ }
+
+ if (isset($noteAttributes['from'])) {
+ $note['from'] = (string) $noteAttributes['from'];
+ }
+
+ $notes[] = $note;
+ }
+
+ return $notes;
+ }
+
+ private function isXmlString(string $resource): bool
+ {
+ return 0 === strpos($resource, '<?xml');
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/YamlFileLoader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/YamlFileLoader.php
new file mode 100644
index 0000000..8588e18
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Loader/YamlFileLoader.php
@@ -0,0 +1,54 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Loader;
+
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+use Symfony\Component\Translation\Exception\LogicException;
+use Symfony\Component\Yaml\Exception\ParseException;
+use Symfony\Component\Yaml\Parser as YamlParser;
+use Symfony\Component\Yaml\Yaml;
+
+/**
+ * YamlFileLoader loads translations from Yaml files.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class YamlFileLoader extends FileLoader
+{
+ private $yamlParser;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function loadResource(string $resource)
+ {
+ if (null === $this->yamlParser) {
+ if (!class_exists(\Symfony\Component\Yaml\Parser::class)) {
+ throw new LogicException('Loading translations from the YAML format requires the Symfony Yaml component.');
+ }
+
+ $this->yamlParser = new YamlParser();
+ }
+
+ try {
+ $messages = $this->yamlParser->parseFile($resource, Yaml::PARSE_CONSTANT);
+ } catch (ParseException $e) {
+ throw new InvalidResourceException(sprintf('The file "%s" does not contain valid YAML: ', $resource).$e->getMessage(), 0, $e);
+ }
+
+ if (null !== $messages && !\is_array($messages)) {
+ throw new InvalidResourceException(sprintf('Unable to load file "%s".', $resource));
+ }
+
+ return $messages ?: [];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/LoggingTranslator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/LoggingTranslator.php
new file mode 100644
index 0000000..bb93435
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/LoggingTranslator.php
@@ -0,0 +1,135 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+use Psr\Log\LoggerInterface;
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Contracts\Translation\LocaleAwareInterface;
+use Symfony\Contracts\Translation\TranslatorInterface;
+
+/**
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+class LoggingTranslator implements TranslatorInterface, TranslatorBagInterface, LocaleAwareInterface
+{
+ /**
+ * @var TranslatorInterface|TranslatorBagInterface
+ */
+ private $translator;
+
+ private $logger;
+
+ /**
+ * @param TranslatorInterface $translator The translator must implement TranslatorBagInterface
+ */
+ public function __construct(TranslatorInterface $translator, LoggerInterface $logger)
+ {
+ if (!$translator instanceof TranslatorBagInterface || !$translator instanceof LocaleAwareInterface) {
+ throw new InvalidArgumentException(sprintf('The Translator "%s" must implement TranslatorInterface, TranslatorBagInterface and LocaleAwareInterface.', get_debug_type($translator)));
+ }
+
+ $this->translator = $translator;
+ $this->logger = $logger;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function trans(?string $id, array $parameters = [], string $domain = null, string $locale = null)
+ {
+ $trans = $this->translator->trans($id = (string) $id, $parameters, $domain, $locale);
+ $this->log($id, $domain, $locale);
+
+ return $trans;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setLocale(string $locale)
+ {
+ $prev = $this->translator->getLocale();
+ $this->translator->setLocale($locale);
+ if ($prev === $locale) {
+ return;
+ }
+
+ $this->logger->debug(sprintf('The locale of the translator has changed from "%s" to "%s".', $prev, $locale));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getLocale()
+ {
+ return $this->translator->getLocale();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCatalogue(string $locale = null)
+ {
+ return $this->translator->getCatalogue($locale);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCatalogues(): array
+ {
+ return $this->translator->getCatalogues();
+ }
+
+ /**
+ * Gets the fallback locales.
+ *
+ * @return array The fallback locales
+ */
+ public function getFallbackLocales()
+ {
+ if ($this->translator instanceof Translator || method_exists($this->translator, 'getFallbackLocales')) {
+ return $this->translator->getFallbackLocales();
+ }
+
+ return [];
+ }
+
+ /**
+ * Passes through all unknown calls onto the translator object.
+ */
+ public function __call(string $method, array $args)
+ {
+ return $this->translator->{$method}(...$args);
+ }
+
+ /**
+ * Logs for missing translations.
+ */
+ private function log(string $id, ?string $domain, ?string $locale)
+ {
+ if (null === $domain) {
+ $domain = 'messages';
+ }
+
+ $catalogue = $this->translator->getCatalogue($locale);
+ if ($catalogue->defines($id, $domain)) {
+ return;
+ }
+
+ if ($catalogue->has($id, $domain)) {
+ $this->logger->debug('Translation use fallback catalogue.', ['id' => $id, 'domain' => $domain, 'locale' => $catalogue->getLocale()]);
+ } else {
+ $this->logger->warning('Translation not found.', ['id' => $id, 'domain' => $domain, 'locale' => $catalogue->getLocale()]);
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/MessageCatalogue.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/MessageCatalogue.php
new file mode 100644
index 0000000..ff49b5a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/MessageCatalogue.php
@@ -0,0 +1,314 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+use Symfony\Component\Config\Resource\ResourceInterface;
+use Symfony\Component\Translation\Exception\LogicException;
+
+/**
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterface
+{
+ private $messages = [];
+ private $metadata = [];
+ private $resources = [];
+ private $locale;
+ private $fallbackCatalogue;
+ private $parent;
+
+ /**
+ * @param array $messages An array of messages classified by domain
+ */
+ public function __construct(string $locale, array $messages = [])
+ {
+ $this->locale = $locale;
+ $this->messages = $messages;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getLocale()
+ {
+ return $this->locale;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getDomains()
+ {
+ $domains = [];
+
+ foreach ($this->messages as $domain => $messages) {
+ if (str_ends_with($domain, self::INTL_DOMAIN_SUFFIX)) {
+ $domain = substr($domain, 0, -\strlen(self::INTL_DOMAIN_SUFFIX));
+ }
+ $domains[$domain] = $domain;
+ }
+
+ return array_values($domains);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function all(string $domain = null)
+ {
+ if (null !== $domain) {
+ // skip messages merge if intl-icu requested explicitly
+ if (str_ends_with($domain, self::INTL_DOMAIN_SUFFIX)) {
+ return $this->messages[$domain] ?? [];
+ }
+
+ return ($this->messages[$domain.self::INTL_DOMAIN_SUFFIX] ?? []) + ($this->messages[$domain] ?? []);
+ }
+
+ $allMessages = [];
+
+ foreach ($this->messages as $domain => $messages) {
+ if (str_ends_with($domain, self::INTL_DOMAIN_SUFFIX)) {
+ $domain = substr($domain, 0, -\strlen(self::INTL_DOMAIN_SUFFIX));
+ $allMessages[$domain] = $messages + ($allMessages[$domain] ?? []);
+ } else {
+ $allMessages[$domain] = ($allMessages[$domain] ?? []) + $messages;
+ }
+ }
+
+ return $allMessages;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set(string $id, string $translation, string $domain = 'messages')
+ {
+ $this->add([$id => $translation], $domain);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function has(string $id, string $domain = 'messages')
+ {
+ if (isset($this->messages[$domain][$id]) || isset($this->messages[$domain.self::INTL_DOMAIN_SUFFIX][$id])) {
+ return true;
+ }
+
+ if (null !== $this->fallbackCatalogue) {
+ return $this->fallbackCatalogue->has($id, $domain);
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function defines(string $id, string $domain = 'messages')
+ {
+ return isset($this->messages[$domain][$id]) || isset($this->messages[$domain.self::INTL_DOMAIN_SUFFIX][$id]);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get(string $id, string $domain = 'messages')
+ {
+ if (isset($this->messages[$domain.self::INTL_DOMAIN_SUFFIX][$id])) {
+ return $this->messages[$domain.self::INTL_DOMAIN_SUFFIX][$id];
+ }
+
+ if (isset($this->messages[$domain][$id])) {
+ return $this->messages[$domain][$id];
+ }
+
+ if (null !== $this->fallbackCatalogue) {
+ return $this->fallbackCatalogue->get($id, $domain);
+ }
+
+ return $id;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function replace(array $messages, string $domain = 'messages')
+ {
+ unset($this->messages[$domain], $this->messages[$domain.self::INTL_DOMAIN_SUFFIX]);
+
+ $this->add($messages, $domain);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function add(array $messages, string $domain = 'messages')
+ {
+ if (!isset($this->messages[$domain])) {
+ $this->messages[$domain] = [];
+ }
+ $intlDomain = $domain;
+ if (!str_ends_with($domain, self::INTL_DOMAIN_SUFFIX)) {
+ $intlDomain .= self::INTL_DOMAIN_SUFFIX;
+ }
+ foreach ($messages as $id => $message) {
+ if (isset($this->messages[$intlDomain]) && \array_key_exists($id, $this->messages[$intlDomain])) {
+ $this->messages[$intlDomain][$id] = $message;
+ } else {
+ $this->messages[$domain][$id] = $message;
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addCatalogue(MessageCatalogueInterface $catalogue)
+ {
+ if ($catalogue->getLocale() !== $this->locale) {
+ throw new LogicException(sprintf('Cannot add a catalogue for locale "%s" as the current locale for this catalogue is "%s".', $catalogue->getLocale(), $this->locale));
+ }
+
+ foreach ($catalogue->all() as $domain => $messages) {
+ if ($intlMessages = $catalogue->all($domain.self::INTL_DOMAIN_SUFFIX)) {
+ $this->add($intlMessages, $domain.self::INTL_DOMAIN_SUFFIX);
+ $messages = array_diff_key($messages, $intlMessages);
+ }
+ $this->add($messages, $domain);
+ }
+
+ foreach ($catalogue->getResources() as $resource) {
+ $this->addResource($resource);
+ }
+
+ if ($catalogue instanceof MetadataAwareInterface) {
+ $metadata = $catalogue->getMetadata('', '');
+ $this->addMetadata($metadata);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addFallbackCatalogue(MessageCatalogueInterface $catalogue)
+ {
+ // detect circular references
+ $c = $catalogue;
+ while ($c = $c->getFallbackCatalogue()) {
+ if ($c->getLocale() === $this->getLocale()) {
+ throw new LogicException(sprintf('Circular reference detected when adding a fallback catalogue for locale "%s".', $catalogue->getLocale()));
+ }
+ }
+
+ $c = $this;
+ do {
+ if ($c->getLocale() === $catalogue->getLocale()) {
+ throw new LogicException(sprintf('Circular reference detected when adding a fallback catalogue for locale "%s".', $catalogue->getLocale()));
+ }
+
+ foreach ($catalogue->getResources() as $resource) {
+ $c->addResource($resource);
+ }
+ } while ($c = $c->parent);
+
+ $catalogue->parent = $this;
+ $this->fallbackCatalogue = $catalogue;
+
+ foreach ($catalogue->getResources() as $resource) {
+ $this->addResource($resource);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFallbackCatalogue()
+ {
+ return $this->fallbackCatalogue;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getResources()
+ {
+ return array_values($this->resources);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addResource(ResourceInterface $resource)
+ {
+ $this->resources[$resource->__toString()] = $resource;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getMetadata(string $key = '', string $domain = 'messages')
+ {
+ if ('' == $domain) {
+ return $this->metadata;
+ }
+
+ if (isset($this->metadata[$domain])) {
+ if ('' == $key) {
+ return $this->metadata[$domain];
+ }
+
+ if (isset($this->metadata[$domain][$key])) {
+ return $this->metadata[$domain][$key];
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setMetadata(string $key, $value, string $domain = 'messages')
+ {
+ $this->metadata[$domain][$key] = $value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function deleteMetadata(string $key = '', string $domain = 'messages')
+ {
+ if ('' == $domain) {
+ $this->metadata = [];
+ } elseif ('' == $key) {
+ unset($this->metadata[$domain]);
+ } else {
+ unset($this->metadata[$domain][$key]);
+ }
+ }
+
+ /**
+ * Adds current values with the new values.
+ *
+ * @param array $values Values to add
+ */
+ private function addMetadata(array $values)
+ {
+ foreach ($values as $domain => $keys) {
+ foreach ($keys as $key => $value) {
+ $this->setMetadata($key, $value, $domain);
+ }
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/MessageCatalogueInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/MessageCatalogueInterface.php
new file mode 100644
index 0000000..5d83bd8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/MessageCatalogueInterface.php
@@ -0,0 +1,138 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+use Symfony\Component\Config\Resource\ResourceInterface;
+
+/**
+ * MessageCatalogueInterface.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface MessageCatalogueInterface
+{
+ public const INTL_DOMAIN_SUFFIX = '+intl-icu';
+
+ /**
+ * Gets the catalogue locale.
+ *
+ * @return string The locale
+ */
+ public function getLocale();
+
+ /**
+ * Gets the domains.
+ *
+ * @return array An array of domains
+ */
+ public function getDomains();
+
+ /**
+ * Gets the messages within a given domain.
+ *
+ * If $domain is null, it returns all messages.
+ *
+ * @param string $domain The domain name
+ *
+ * @return array An array of messages
+ */
+ public function all(string $domain = null);
+
+ /**
+ * Sets a message translation.
+ *
+ * @param string $id The message id
+ * @param string $translation The messages translation
+ * @param string $domain The domain name
+ */
+ public function set(string $id, string $translation, string $domain = 'messages');
+
+ /**
+ * Checks if a message has a translation.
+ *
+ * @param string $id The message id
+ * @param string $domain The domain name
+ *
+ * @return bool true if the message has a translation, false otherwise
+ */
+ public function has(string $id, string $domain = 'messages');
+
+ /**
+ * Checks if a message has a translation (it does not take into account the fallback mechanism).
+ *
+ * @param string $id The message id
+ * @param string $domain The domain name
+ *
+ * @return bool true if the message has a translation, false otherwise
+ */
+ public function defines(string $id, string $domain = 'messages');
+
+ /**
+ * Gets a message translation.
+ *
+ * @param string $id The message id
+ * @param string $domain The domain name
+ *
+ * @return string The message translation
+ */
+ public function get(string $id, string $domain = 'messages');
+
+ /**
+ * Sets translations for a given domain.
+ *
+ * @param array $messages An array of translations
+ * @param string $domain The domain name
+ */
+ public function replace(array $messages, string $domain = 'messages');
+
+ /**
+ * Adds translations for a given domain.
+ *
+ * @param array $messages An array of translations
+ * @param string $domain The domain name
+ */
+ public function add(array $messages, string $domain = 'messages');
+
+ /**
+ * Merges translations from the given Catalogue into the current one.
+ *
+ * The two catalogues must have the same locale.
+ */
+ public function addCatalogue(self $catalogue);
+
+ /**
+ * Merges translations from the given Catalogue into the current one
+ * only when the translation does not exist.
+ *
+ * This is used to provide default translations when they do not exist for the current locale.
+ */
+ public function addFallbackCatalogue(self $catalogue);
+
+ /**
+ * Gets the fallback catalogue.
+ *
+ * @return self|null A MessageCatalogueInterface instance or null when no fallback has been set
+ */
+ public function getFallbackCatalogue();
+
+ /**
+ * Returns an array of resources loaded to build this collection.
+ *
+ * @return ResourceInterface[] An array of resources
+ */
+ public function getResources();
+
+ /**
+ * Adds a resource for this collection.
+ */
+ public function addResource(ResourceInterface $resource);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/MetadataAwareInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/MetadataAwareInterface.php
new file mode 100644
index 0000000..2216eed
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/MetadataAwareInterface.php
@@ -0,0 +1,46 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+/**
+ * MetadataAwareInterface.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface MetadataAwareInterface
+{
+ /**
+ * Gets metadata for the given domain and key.
+ *
+ * Passing an empty domain will return an array with all metadata indexed by
+ * domain and then by key. Passing an empty key will return an array with all
+ * metadata for the given domain.
+ *
+ * @return mixed The value that was set or an array with the domains/keys or null
+ */
+ public function getMetadata(string $key = '', string $domain = 'messages');
+
+ /**
+ * Adds metadata to a message domain.
+ *
+ * @param mixed $value
+ */
+ public function setMetadata(string $key, $value, string $domain = 'messages');
+
+ /**
+ * Deletes metadata for the given key and domain.
+ *
+ * Passing an empty domain will delete all metadata. Passing an empty key will
+ * delete all metadata for the given domain.
+ */
+ public function deleteMetadata(string $key = '', string $domain = 'messages');
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/AbstractProviderFactory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/AbstractProviderFactory.php
new file mode 100644
index 0000000..17442fd
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/AbstractProviderFactory.php
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Provider;
+
+use Symfony\Component\Translation\Exception\IncompleteDsnException;
+
+abstract class AbstractProviderFactory implements ProviderFactoryInterface
+{
+ public function supports(Dsn $dsn): bool
+ {
+ return \in_array($dsn->getScheme(), $this->getSupportedSchemes(), true);
+ }
+
+ /**
+ * @return string[]
+ */
+ abstract protected function getSupportedSchemes(): array;
+
+ protected function getUser(Dsn $dsn): string
+ {
+ if (null === $user = $dsn->getUser()) {
+ throw new IncompleteDsnException('User is not set.', $dsn->getOriginalDsn());
+ }
+
+ return $user;
+ }
+
+ protected function getPassword(Dsn $dsn): string
+ {
+ if (null === $password = $dsn->getPassword()) {
+ throw new IncompleteDsnException('Password is not set.', $dsn->getOriginalDsn());
+ }
+
+ return $password;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/Dsn.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/Dsn.php
new file mode 100644
index 0000000..820cabf
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/Dsn.php
@@ -0,0 +1,110 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Provider;
+
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\Exception\MissingRequiredOptionException;
+
+/**
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Oskar Stark <oskarstark@googlemail.com>
+ */
+final class Dsn
+{
+ private $scheme;
+ private $host;
+ private $user;
+ private $password;
+ private $port;
+ private $path;
+ private $options;
+ private $originalDsn;
+
+ public function __construct(string $dsn)
+ {
+ $this->originalDsn = $dsn;
+
+ if (false === $parsedDsn = parse_url($dsn)) {
+ throw new InvalidArgumentException(sprintf('The "%s" translation provider DSN is invalid.', $dsn));
+ }
+
+ if (!isset($parsedDsn['scheme'])) {
+ throw new InvalidArgumentException(sprintf('The "%s" translation provider DSN must contain a scheme.', $dsn));
+ }
+ $this->scheme = $parsedDsn['scheme'];
+
+ if (!isset($parsedDsn['host'])) {
+ throw new InvalidArgumentException(sprintf('The "%s" translation provider DSN must contain a host (use "default" by default).', $dsn));
+ }
+ $this->host = $parsedDsn['host'];
+
+ $this->user = '' !== ($parsedDsn['user'] ?? '') ? urldecode($parsedDsn['user']) : null;
+ $this->password = '' !== ($parsedDsn['pass'] ?? '') ? urldecode($parsedDsn['pass']) : null;
+ $this->port = $parsedDsn['port'] ?? null;
+ $this->path = $parsedDsn['path'] ?? null;
+ parse_str($parsedDsn['query'] ?? '', $this->options);
+ }
+
+ public function getScheme(): string
+ {
+ return $this->scheme;
+ }
+
+ public function getHost(): string
+ {
+ return $this->host;
+ }
+
+ public function getUser(): ?string
+ {
+ return $this->user;
+ }
+
+ public function getPassword(): ?string
+ {
+ return $this->password;
+ }
+
+ public function getPort(int $default = null): ?int
+ {
+ return $this->port ?? $default;
+ }
+
+ public function getOption(string $key, $default = null)
+ {
+ return $this->options[$key] ?? $default;
+ }
+
+ public function getRequiredOption(string $key)
+ {
+ if (!\array_key_exists($key, $this->options) || '' === trim($this->options[$key])) {
+ throw new MissingRequiredOptionException($key);
+ }
+
+ return $this->options[$key];
+ }
+
+ public function getOptions(): array
+ {
+ return $this->options;
+ }
+
+ public function getPath(): ?string
+ {
+ return $this->path;
+ }
+
+ public function getOriginalDsn(): string
+ {
+ return $this->originalDsn;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/FilteringProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/FilteringProvider.php
new file mode 100644
index 0000000..0307cda
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/FilteringProvider.php
@@ -0,0 +1,67 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Provider;
+
+use Symfony\Component\Translation\TranslatorBag;
+use Symfony\Component\Translation\TranslatorBagInterface;
+
+/**
+ * Filters domains and locales between the Translator config values and those specific to each provider.
+ *
+ * @author Mathieu Santostefano <msantostefano@protonmail.com>
+ *
+ * @experimental in 5.3
+ */
+class FilteringProvider implements ProviderInterface
+{
+ private $provider;
+ private $locales;
+ private $domains;
+
+ public function __construct(ProviderInterface $provider, array $locales, array $domains = [])
+ {
+ $this->provider = $provider;
+ $this->locales = $locales;
+ $this->domains = $domains;
+ }
+
+ public function __toString(): string
+ {
+ return (string) $this->provider;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function write(TranslatorBagInterface $translatorBag): void
+ {
+ $this->provider->write($translatorBag);
+ }
+
+ public function read(array $domains, array $locales): TranslatorBag
+ {
+ $domains = !$this->domains ? $domains : array_intersect($this->domains, $domains);
+ $locales = array_intersect($this->locales, $locales);
+
+ return $this->provider->read($domains, $locales);
+ }
+
+ public function delete(TranslatorBagInterface $translatorBag): void
+ {
+ $this->provider->delete($translatorBag);
+ }
+
+ public function getDomains(): array
+ {
+ return $this->domains;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/NullProvider.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/NullProvider.php
new file mode 100644
index 0000000..785fcaa
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/NullProvider.php
@@ -0,0 +1,41 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Provider;
+
+use Symfony\Component\Translation\TranslatorBag;
+use Symfony\Component\Translation\TranslatorBagInterface;
+
+/**
+ * @author Mathieu Santostefano <msantostefano@protonmail.com>
+ *
+ * @experimental in 5.3
+ */
+class NullProvider implements ProviderInterface
+{
+ public function __toString(): string
+ {
+ return 'null';
+ }
+
+ public function write(TranslatorBagInterface $translatorBag, bool $override = false): void
+ {
+ }
+
+ public function read(array $domains, array $locales): TranslatorBag
+ {
+ return new TranslatorBag();
+ }
+
+ public function delete(TranslatorBagInterface $translatorBag): void
+ {
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/NullProviderFactory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/NullProviderFactory.php
new file mode 100644
index 0000000..6ddbd85
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/NullProviderFactory.php
@@ -0,0 +1,36 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Provider;
+
+use Symfony\Component\Translation\Exception\UnsupportedSchemeException;
+
+/**
+ * @author Mathieu Santostefano <msantostefano@protonmail.com>
+ *
+ * @experimental in 5.3
+ */
+final class NullProviderFactory extends AbstractProviderFactory
+{
+ public function create(Dsn $dsn): ProviderInterface
+ {
+ if ('null' === $dsn->getScheme()) {
+ return new NullProvider();
+ }
+
+ throw new UnsupportedSchemeException($dsn, 'null', $this->getSupportedSchemes());
+ }
+
+ protected function getSupportedSchemes(): array
+ {
+ return ['null'];
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/ProviderFactoryInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/ProviderFactoryInterface.php
new file mode 100644
index 0000000..3fd4494
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/ProviderFactoryInterface.php
@@ -0,0 +1,26 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Provider;
+
+use Symfony\Component\Translation\Exception\IncompleteDsnException;
+use Symfony\Component\Translation\Exception\UnsupportedSchemeException;
+
+interface ProviderFactoryInterface
+{
+ /**
+ * @throws UnsupportedSchemeException
+ * @throws IncompleteDsnException
+ */
+ public function create(Dsn $dsn): ProviderInterface;
+
+ public function supports(Dsn $dsn): bool;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/ProviderInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/ProviderInterface.php
new file mode 100644
index 0000000..a32193f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/ProviderInterface.php
@@ -0,0 +1,32 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Provider;
+
+use Symfony\Component\Translation\TranslatorBag;
+use Symfony\Component\Translation\TranslatorBagInterface;
+
+interface ProviderInterface
+{
+ public function __toString(): string;
+
+ /**
+ * Translations available in the TranslatorBag only must be created.
+ * Translations available in both the TranslatorBag and on the provider
+ * must be overwritten.
+ * Translations available on the provider only must be kept.
+ */
+ public function write(TranslatorBagInterface $translatorBag): void;
+
+ public function read(array $domains, array $locales): TranslatorBag;
+
+ public function delete(TranslatorBagInterface $translatorBag): void;
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/TranslationProviderCollection.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/TranslationProviderCollection.php
new file mode 100644
index 0000000..9963cb9
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/TranslationProviderCollection.php
@@ -0,0 +1,59 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Provider;
+
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+
+/**
+ * @author Mathieu Santostefano <msantostefano@protonmail.com>
+ *
+ * @experimental in 5.3
+ */
+final class TranslationProviderCollection
+{
+ private $providers;
+
+ /**
+ * @param array<string, ProviderInterface> $providers
+ */
+ public function __construct(iterable $providers)
+ {
+ $this->providers = [];
+ foreach ($providers as $name => $provider) {
+ $this->providers[$name] = $provider;
+ }
+ }
+
+ public function __toString(): string
+ {
+ return '['.implode(',', array_keys($this->providers)).']';
+ }
+
+ public function has(string $name): bool
+ {
+ return isset($this->providers[$name]);
+ }
+
+ public function get(string $name): ProviderInterface
+ {
+ if (!$this->has($name)) {
+ throw new InvalidArgumentException(sprintf('Provider "%s" not found. Available: "%s".', $name, (string) $this));
+ }
+
+ return $this->providers[$name];
+ }
+
+ public function keys(): array
+ {
+ return array_keys($this->providers);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/TranslationProviderCollectionFactory.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/TranslationProviderCollectionFactory.php
new file mode 100644
index 0000000..43f4a34
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Provider/TranslationProviderCollectionFactory.php
@@ -0,0 +1,59 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Provider;
+
+use Symfony\Component\Translation\Exception\UnsupportedSchemeException;
+
+/**
+ * @author Mathieu Santostefano <msantostefano@protonmail.com>
+ *
+ * @experimental in 5.3
+ */
+class TranslationProviderCollectionFactory
+{
+ private $factories;
+ private $enabledLocales;
+
+ /**
+ * @param ProviderFactoryInterface[] $factories
+ */
+ public function __construct(iterable $factories, array $enabledLocales)
+ {
+ $this->factories = $factories;
+ $this->enabledLocales = $enabledLocales;
+ }
+
+ public function fromConfig(array $config): TranslationProviderCollection
+ {
+ $providers = [];
+ foreach ($config as $name => $currentConfig) {
+ $providers[$name] = $this->fromDsnObject(
+ new Dsn($currentConfig['dsn']),
+ !$currentConfig['locales'] ? $this->enabledLocales : $currentConfig['locales'],
+ !$currentConfig['domains'] ? [] : $currentConfig['domains']
+ );
+ }
+
+ return new TranslationProviderCollection($providers);
+ }
+
+ public function fromDsnObject(Dsn $dsn, array $locales, array $domains = []): ProviderInterface
+ {
+ foreach ($this->factories as $factory) {
+ if ($factory->supports($dsn)) {
+ return new FilteringProvider($factory->create($dsn), $locales, $domains);
+ }
+ }
+
+ throw new UnsupportedSchemeException($dsn);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/PseudoLocalizationTranslator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/PseudoLocalizationTranslator.php
new file mode 100644
index 0000000..49f122e
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/PseudoLocalizationTranslator.php
@@ -0,0 +1,364 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+use Symfony\Contracts\Translation\TranslatorInterface;
+
+/**
+ * This translator should only be used in a development environment.
+ */
+final class PseudoLocalizationTranslator implements TranslatorInterface
+{
+ private const EXPANSION_CHARACTER = '~';
+
+ private $translator;
+ private $accents;
+ private $expansionFactor;
+ private $brackets;
+ private $parseHTML;
+ private $localizableHTMLAttributes;
+
+ /**
+ * Available options:
+ * * accents:
+ * type: boolean
+ * default: true
+ * description: replace ASCII characters of the translated string with accented versions or similar characters
+ * example: if true, "foo" => "ƒöö".
+ *
+ * * expansion_factor:
+ * type: float
+ * default: 1
+ * validation: it must be greater than or equal to 1
+ * description: expand the translated string by the given factor with spaces and tildes
+ * example: if 2, "foo" => "~foo ~"
+ *
+ * * brackets:
+ * type: boolean
+ * default: true
+ * description: wrap the translated string with brackets
+ * example: if true, "foo" => "[foo]"
+ *
+ * * parse_html:
+ * type: boolean
+ * default: false
+ * description: parse the translated string as HTML - looking for HTML tags has a performance impact but allows to preserve them from alterations - it also allows to compute the visible translated string length which is useful to correctly expand ot when it contains HTML
+ * warning: unclosed tags are unsupported, they will be fixed (closed) by the parser - eg, "foo <div>bar" => "foo <div>bar</div>"
+ *
+ * * localizable_html_attributes:
+ * type: string[]
+ * default: []
+ * description: the list of HTML attributes whose values can be altered - it is only useful when the "parse_html" option is set to true
+ * example: if ["title"], and with the "accents" option set to true, "<a href="#" title="Go to your profile">Profile</a>" => "<a href="#" title="Ĝö ţö ýöûŕ þŕöƒîļé">Þŕöƒîļé</a>" - if "title" was not in the "localizable_html_attributes" list, the title attribute data would be left unchanged.
+ */
+ public function __construct(TranslatorInterface $translator, array $options = [])
+ {
+ $this->translator = $translator;
+ $this->accents = $options['accents'] ?? true;
+
+ if (1.0 > ($this->expansionFactor = $options['expansion_factor'] ?? 1.0)) {
+ throw new \InvalidArgumentException('The expansion factor must be greater than or equal to 1.');
+ }
+
+ $this->brackets = $options['brackets'] ?? true;
+
+ $this->parseHTML = $options['parse_html'] ?? false;
+ if ($this->parseHTML && !$this->accents && 1.0 === $this->expansionFactor) {
+ $this->parseHTML = false;
+ }
+
+ $this->localizableHTMLAttributes = $options['localizable_html_attributes'] ?? [];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function trans(string $id, array $parameters = [], string $domain = null, string $locale = null)
+ {
+ $trans = '';
+ $visibleText = '';
+
+ foreach ($this->getParts($this->translator->trans($id, $parameters, $domain, $locale)) as [$visible, $localizable, $text]) {
+ if ($visible) {
+ $visibleText .= $text;
+ }
+
+ if (!$localizable) {
+ $trans .= $text;
+
+ continue;
+ }
+
+ $this->addAccents($trans, $text);
+ }
+
+ $this->expand($trans, $visibleText);
+
+ $this->addBrackets($trans);
+
+ return $trans;
+ }
+
+ public function getLocale(): string
+ {
+ return $this->translator->getLocale();
+ }
+
+ private function getParts(string $originalTrans): array
+ {
+ if (!$this->parseHTML) {
+ return [[true, true, $originalTrans]];
+ }
+
+ $html = mb_convert_encoding($originalTrans, 'HTML-ENTITIES', mb_detect_encoding($originalTrans, null, true) ?: 'UTF-8');
+
+ $useInternalErrors = libxml_use_internal_errors(true);
+
+ $dom = new \DOMDocument();
+ $dom->loadHTML('<trans>'.$html.'</trans>');
+
+ libxml_clear_errors();
+ libxml_use_internal_errors($useInternalErrors);
+
+ return $this->parseNode($dom->childNodes->item(1)->childNodes->item(0)->childNodes->item(0));
+ }
+
+ private function parseNode(\DOMNode $node): array
+ {
+ $parts = [];
+
+ foreach ($node->childNodes as $childNode) {
+ if (!$childNode instanceof \DOMElement) {
+ $parts[] = [true, true, $childNode->nodeValue];
+
+ continue;
+ }
+
+ $parts[] = [false, false, '<'.$childNode->tagName];
+
+ /** @var \DOMAttr $attribute */
+ foreach ($childNode->attributes as $attribute) {
+ $parts[] = [false, false, ' '.$attribute->nodeName.'="'];
+
+ $localizableAttribute = \in_array($attribute->nodeName, $this->localizableHTMLAttributes, true);
+ foreach (preg_split('/(&(?:amp|quot|#039|lt|gt);+)/', htmlspecialchars($attribute->nodeValue, \ENT_QUOTES, 'UTF-8'), -1, \PREG_SPLIT_DELIM_CAPTURE) as $i => $match) {
+ if ('' === $match) {
+ continue;
+ }
+
+ $parts[] = [false, $localizableAttribute && 0 === $i % 2, $match];
+ }
+
+ $parts[] = [false, false, '"'];
+ }
+
+ $parts[] = [false, false, '>'];
+
+ $parts = array_merge($parts, $this->parseNode($childNode, $parts));
+
+ $parts[] = [false, false, '</'.$childNode->tagName.'>'];
+ }
+
+ return $parts;
+ }
+
+ private function addAccents(string &$trans, string $text): void
+ {
+ $trans .= $this->accents ? strtr($text, [
+ ' ' => ' ',
+ '!' => '¡',
+ '"' => '″',
+ '#' => '♯',
+ '$' => '€',
+ '%' => '‰',
+ '&' => '⅋',
+ '\'' => '´',
+ '(' => '{',
+ ')' => '}',
+ '*' => '⁎',
+ '+' => '⁺',
+ ',' => '،',
+ '-' => '‐',
+ '.' => '·',
+ '/' => '⁄',
+ '0' => '⓪',
+ '1' => '①',
+ '2' => '②',
+ '3' => '③',
+ '4' => '④',
+ '5' => '⑤',
+ '6' => '⑥',
+ '7' => '⑦',
+ '8' => '⑧',
+ '9' => '⑨',
+ ':' => '∶',
+ ';' => '⁏',
+ '<' => '≤',
+ '=' => '≂',
+ '>' => '≥',
+ '?' => '¿',
+ '@' => '՞',
+ 'A' => 'Å',
+ 'B' => 'Ɓ',
+ 'C' => 'Ç',
+ 'D' => 'Ð',
+ 'E' => 'É',
+ 'F' => 'Ƒ',
+ 'G' => 'Ĝ',
+ 'H' => 'Ĥ',
+ 'I' => 'Î',
+ 'J' => 'Ĵ',
+ 'K' => 'Ķ',
+ 'L' => 'Ļ',
+ 'M' => 'Ṁ',
+ 'N' => 'Ñ',
+ 'O' => 'Ö',
+ 'P' => 'Þ',
+ 'Q' => 'Ǫ',
+ 'R' => 'Ŕ',
+ 'S' => 'Š',
+ 'T' => 'Ţ',
+ 'U' => 'Û',
+ 'V' => 'Ṽ',
+ 'W' => 'Ŵ',
+ 'X' => 'Ẋ',
+ 'Y' => 'Ý',
+ 'Z' => 'Ž',
+ '[' => '⁅',
+ '\\' => '∖',
+ ']' => '⁆',
+ '^' => '˄',
+ '_' => '‿',
+ '`' => '‵',
+ 'a' => 'å',
+ 'b' => 'ƀ',
+ 'c' => 'ç',
+ 'd' => 'ð',
+ 'e' => 'é',
+ 'f' => 'ƒ',
+ 'g' => 'ĝ',
+ 'h' => 'ĥ',
+ 'i' => 'î',
+ 'j' => 'ĵ',
+ 'k' => 'ķ',
+ 'l' => 'ļ',
+ 'm' => 'ɱ',
+ 'n' => 'ñ',
+ 'o' => 'ö',
+ 'p' => 'þ',
+ 'q' => 'ǫ',
+ 'r' => 'ŕ',
+ 's' => 'š',
+ 't' => 'ţ',
+ 'u' => 'û',
+ 'v' => 'ṽ',
+ 'w' => 'ŵ',
+ 'x' => 'ẋ',
+ 'y' => 'ý',
+ 'z' => 'ž',
+ '{' => '(',
+ '|' => '¦',
+ '}' => ')',
+ '~' => '˞',
+ ]) : $text;
+ }
+
+ private function expand(string &$trans, string $visibleText): void
+ {
+ if (1.0 >= $this->expansionFactor) {
+ return;
+ }
+
+ $visibleLength = $this->strlen($visibleText);
+ $missingLength = (int) (ceil($visibleLength * $this->expansionFactor)) - $visibleLength;
+ if ($this->brackets) {
+ $missingLength -= 2;
+ }
+
+ if (0 >= $missingLength) {
+ return;
+ }
+
+ $words = [];
+ $wordsCount = 0;
+ foreach (preg_split('/ +/', $visibleText, -1, \PREG_SPLIT_NO_EMPTY) as $word) {
+ $wordLength = $this->strlen($word);
+
+ if ($wordLength >= $missingLength) {
+ continue;
+ }
+
+ if (!isset($words[$wordLength])) {
+ $words[$wordLength] = 0;
+ }
+
+ ++$words[$wordLength];
+ ++$wordsCount;
+ }
+
+ if (!$words) {
+ $trans .= 1 === $missingLength ? self::EXPANSION_CHARACTER : ' '.str_repeat(self::EXPANSION_CHARACTER, $missingLength - 1);
+
+ return;
+ }
+
+ arsort($words, \SORT_NUMERIC);
+
+ $longestWordLength = max(array_keys($words));
+
+ while (true) {
+ $r = mt_rand(1, $wordsCount);
+
+ foreach ($words as $length => $count) {
+ $r -= $count;
+ if ($r <= 0) {
+ break;
+ }
+ }
+
+ $trans .= ' '.str_repeat(self::EXPANSION_CHARACTER, $length);
+
+ $missingLength -= $length + 1;
+
+ if (0 === $missingLength) {
+ return;
+ }
+
+ while ($longestWordLength >= $missingLength) {
+ $wordsCount -= $words[$longestWordLength];
+ unset($words[$longestWordLength]);
+
+ if (!$words) {
+ $trans .= 1 === $missingLength ? self::EXPANSION_CHARACTER : ' '.str_repeat(self::EXPANSION_CHARACTER, $missingLength - 1);
+
+ return;
+ }
+
+ $longestWordLength = max(array_keys($words));
+ }
+ }
+ }
+
+ private function addBrackets(string &$trans): void
+ {
+ if (!$this->brackets) {
+ return;
+ }
+
+ $trans = '['.$trans.']';
+ }
+
+ private function strlen(string $s): int
+ {
+ return false === ($encoding = mb_detect_encoding($s, null, true)) ? \strlen($s) : mb_strlen($s, $encoding);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/README.md b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/README.md
new file mode 100644
index 0000000..720bee3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/README.md
@@ -0,0 +1,33 @@
+Translation Component
+=====================
+
+The Translation component provides tools to internationalize your application.
+
+Getting Started
+---------------
+
+```
+$ composer require symfony/translation
+```
+
+```php
+use Symfony\Component\Translation\Translator;
+use Symfony\Component\Translation\Loader\ArrayLoader;
+
+$translator = new Translator('fr_FR');
+$translator->addLoader('array', new ArrayLoader());
+$translator->addResource('array', [
+ 'Hello World!' => 'Bonjour !',
+], 'fr_FR');
+
+echo $translator->trans('Hello World!'); // outputs « Bonjour ! »
+```
+
+Resources
+---------
+
+ * [Documentation](https://symfony.com/doc/current/translation.html)
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/symfony/issues) and
+ [send Pull Requests](https://github.com/symfony/symfony/pulls)
+ in the [main Symfony repository](https://github.com/symfony/symfony)
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Reader/TranslationReader.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Reader/TranslationReader.php
new file mode 100644
index 0000000..9e51b15
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Reader/TranslationReader.php
@@ -0,0 +1,62 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Reader;
+
+use Symfony\Component\Finder\Finder;
+use Symfony\Component\Translation\Loader\LoaderInterface;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * TranslationReader reads translation messages from translation files.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+class TranslationReader implements TranslationReaderInterface
+{
+ /**
+ * Loaders used for import.
+ *
+ * @var array
+ */
+ private $loaders = [];
+
+ /**
+ * Adds a loader to the translation extractor.
+ *
+ * @param string $format The format of the loader
+ */
+ public function addLoader(string $format, LoaderInterface $loader)
+ {
+ $this->loaders[$format] = $loader;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function read(string $directory, MessageCatalogue $catalogue)
+ {
+ if (!is_dir($directory)) {
+ return;
+ }
+
+ foreach ($this->loaders as $format => $loader) {
+ // load any existing translation files
+ $finder = new Finder();
+ $extension = $catalogue->getLocale().'.'.$format;
+ $files = $finder->files()->name('*.'.$extension)->in($directory);
+ foreach ($files as $file) {
+ $domain = substr($file->getFilename(), 0, -1 * \strlen($extension) - 1);
+ $catalogue->addCatalogue($loader->load($file->getPathname(), $catalogue->getLocale(), $domain));
+ }
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Reader/TranslationReaderInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Reader/TranslationReaderInterface.php
new file mode 100644
index 0000000..bc37204
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Reader/TranslationReaderInterface.php
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Reader;
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * TranslationReader reads translation messages from translation files.
+ *
+ * @author Tobias Nyholm <tobias.nyholm@gmail.com>
+ */
+interface TranslationReaderInterface
+{
+ /**
+ * Reads translation messages from a directory to the catalogue.
+ */
+ public function read(string $directory, MessageCatalogue $catalogue);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/bin/translation-status.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/bin/translation-status.php
new file mode 100644
index 0000000..4e0723b
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/bin/translation-status.php
@@ -0,0 +1,207 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+$usageInstructions = <<<END
+
+ Usage instructions
+ -------------------------------------------------------------------------------
+
+ $ cd symfony-code-root-directory/
+
+ # show the translation status of all locales
+ $ php translation-status.php
+
+ # show the translation status of all locales and all their missing translations
+ $ php translation-status.php -v
+
+ # show the status of a single locale
+ $ php translation-status.php fr
+
+ # show the status of a single locale and all its missing translations
+ $ php translation-status.php fr -v
+
+END;
+
+$config = [
+ // if TRUE, the full list of missing translations is displayed
+ 'verbose_output' => false,
+ // NULL = analyze all locales
+ 'locale_to_analyze' => null,
+ // the reference files all the other translations are compared to
+ 'original_files' => [
+ 'src/Symfony/Component/Form/Resources/translations/validators.en.xlf',
+ 'src/Symfony/Component/Security/Core/Resources/translations/security.en.xlf',
+ 'src/Symfony/Component/Validator/Resources/translations/validators.en.xlf',
+ ],
+];
+
+$argc = $_SERVER['argc'];
+$argv = $_SERVER['argv'];
+
+if ($argc > 3) {
+ echo str_replace('translation-status.php', $argv[0], $usageInstructions);
+ exit(1);
+}
+
+foreach (array_slice($argv, 1) as $argumentOrOption) {
+ if (str_starts_with($argumentOrOption, '-')) {
+ $config['verbose_output'] = true;
+ } else {
+ $config['locale_to_analyze'] = $argumentOrOption;
+ }
+}
+
+foreach ($config['original_files'] as $originalFilePath) {
+ if (!file_exists($originalFilePath)) {
+ echo sprintf('The following file does not exist. Make sure that you execute this command at the root dir of the Symfony code repository.%s %s', \PHP_EOL, $originalFilePath);
+ exit(1);
+ }
+}
+
+$totalMissingTranslations = 0;
+
+foreach ($config['original_files'] as $originalFilePath) {
+ $translationFilePaths = findTranslationFiles($originalFilePath, $config['locale_to_analyze']);
+ $translationStatus = calculateTranslationStatus($originalFilePath, $translationFilePaths);
+
+ $totalMissingTranslations += array_sum(array_map(function ($translation) {
+ return count($translation['missingKeys']);
+ }, array_values($translationStatus)));
+
+ printTranslationStatus($originalFilePath, $translationStatus, $config['verbose_output']);
+}
+
+exit($totalMissingTranslations > 0 ? 1 : 0);
+
+function findTranslationFiles($originalFilePath, $localeToAnalyze)
+{
+ $translations = [];
+
+ $translationsDir = dirname($originalFilePath);
+ $originalFileName = basename($originalFilePath);
+ $translationFileNamePattern = str_replace('.en.', '.*.', $originalFileName);
+
+ $translationFiles = glob($translationsDir.'/'.$translationFileNamePattern, \GLOB_NOSORT);
+ sort($translationFiles);
+ foreach ($translationFiles as $filePath) {
+ $locale = extractLocaleFromFilePath($filePath);
+
+ if (null !== $localeToAnalyze && $locale !== $localeToAnalyze) {
+ continue;
+ }
+
+ $translations[$locale] = $filePath;
+ }
+
+ return $translations;
+}
+
+function calculateTranslationStatus($originalFilePath, $translationFilePaths)
+{
+ $translationStatus = [];
+ $allTranslationKeys = extractTranslationKeys($originalFilePath);
+
+ foreach ($translationFilePaths as $locale => $translationPath) {
+ $translatedKeys = extractTranslationKeys($translationPath);
+ $missingKeys = array_diff_key($allTranslationKeys, $translatedKeys);
+
+ $translationStatus[$locale] = [
+ 'total' => count($allTranslationKeys),
+ 'translated' => count($translatedKeys),
+ 'missingKeys' => $missingKeys,
+ ];
+ }
+
+ return $translationStatus;
+}
+
+function printTranslationStatus($originalFilePath, $translationStatus, $verboseOutput)
+{
+ printTitle($originalFilePath);
+ printTable($translationStatus, $verboseOutput);
+ echo \PHP_EOL.\PHP_EOL;
+}
+
+function extractLocaleFromFilePath($filePath)
+{
+ $parts = explode('.', $filePath);
+
+ return $parts[count($parts) - 2];
+}
+
+function extractTranslationKeys($filePath)
+{
+ $translationKeys = [];
+ $contents = new \SimpleXMLElement(file_get_contents($filePath));
+
+ foreach ($contents->file->body->{'trans-unit'} as $translationKey) {
+ $translationId = (string) $translationKey['id'];
+ $translationKey = (string) $translationKey->source;
+
+ $translationKeys[$translationId] = $translationKey;
+ }
+
+ return $translationKeys;
+}
+
+function printTitle($title)
+{
+ echo $title.\PHP_EOL;
+ echo str_repeat('=', strlen($title)).\PHP_EOL.\PHP_EOL;
+}
+
+function printTable($translations, $verboseOutput)
+{
+ if (0 === count($translations)) {
+ echo 'No translations found';
+
+ return;
+ }
+ $longestLocaleNameLength = max(array_map('strlen', array_keys($translations)));
+
+ foreach ($translations as $locale => $translation) {
+ if ($translation['translated'] > $translation['total']) {
+ textColorRed();
+ } elseif ($translation['translated'] === $translation['total']) {
+ textColorGreen();
+ }
+
+ echo sprintf('| Locale: %-'.$longestLocaleNameLength.'s | Translated: %d/%d', $locale, $translation['translated'], $translation['total']).\PHP_EOL;
+
+ textColorNormal();
+
+ if (true === $verboseOutput && count($translation['missingKeys']) > 0) {
+ echo str_repeat('-', 80).\PHP_EOL;
+ echo '| Missing Translations:'.\PHP_EOL;
+
+ foreach ($translation['missingKeys'] as $id => $content) {
+ echo sprintf('| (id=%s) %s', $id, $content).\PHP_EOL;
+ }
+
+ echo str_repeat('-', 80).\PHP_EOL;
+ }
+ }
+}
+
+function textColorGreen()
+{
+ echo "\033[32m";
+}
+
+function textColorRed()
+{
+ echo "\033[31m";
+}
+
+function textColorNormal()
+{
+ echo "\033[0m";
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/data/parents.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/data/parents.json
new file mode 100644
index 0000000..a67458a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/data/parents.json
@@ -0,0 +1,140 @@
+{
+ "az_Cyrl": "root",
+ "bs_Cyrl": "root",
+ "en_150": "en_001",
+ "en_AG": "en_001",
+ "en_AI": "en_001",
+ "en_AT": "en_150",
+ "en_AU": "en_001",
+ "en_BB": "en_001",
+ "en_BE": "en_150",
+ "en_BM": "en_001",
+ "en_BS": "en_001",
+ "en_BW": "en_001",
+ "en_BZ": "en_001",
+ "en_CA": "en_001",
+ "en_CC": "en_001",
+ "en_CH": "en_150",
+ "en_CK": "en_001",
+ "en_CM": "en_001",
+ "en_CX": "en_001",
+ "en_CY": "en_001",
+ "en_DE": "en_150",
+ "en_DG": "en_001",
+ "en_DK": "en_150",
+ "en_DM": "en_001",
+ "en_ER": "en_001",
+ "en_FI": "en_150",
+ "en_FJ": "en_001",
+ "en_FK": "en_001",
+ "en_FM": "en_001",
+ "en_GB": "en_001",
+ "en_GD": "en_001",
+ "en_GG": "en_001",
+ "en_GH": "en_001",
+ "en_GI": "en_001",
+ "en_GM": "en_001",
+ "en_GY": "en_001",
+ "en_HK": "en_001",
+ "en_IE": "en_001",
+ "en_IL": "en_001",
+ "en_IM": "en_001",
+ "en_IN": "en_001",
+ "en_IO": "en_001",
+ "en_JE": "en_001",
+ "en_JM": "en_001",
+ "en_KE": "en_001",
+ "en_KI": "en_001",
+ "en_KN": "en_001",
+ "en_KY": "en_001",
+ "en_LC": "en_001",
+ "en_LR": "en_001",
+ "en_LS": "en_001",
+ "en_MG": "en_001",
+ "en_MO": "en_001",
+ "en_MS": "en_001",
+ "en_MT": "en_001",
+ "en_MU": "en_001",
+ "en_MW": "en_001",
+ "en_MY": "en_001",
+ "en_NA": "en_001",
+ "en_NF": "en_001",
+ "en_NG": "en_001",
+ "en_NL": "en_150",
+ "en_NR": "en_001",
+ "en_NU": "en_001",
+ "en_NZ": "en_001",
+ "en_PG": "en_001",
+ "en_PH": "en_001",
+ "en_PK": "en_001",
+ "en_PN": "en_001",
+ "en_PW": "en_001",
+ "en_RW": "en_001",
+ "en_SB": "en_001",
+ "en_SC": "en_001",
+ "en_SD": "en_001",
+ "en_SE": "en_150",
+ "en_SG": "en_001",
+ "en_SH": "en_001",
+ "en_SI": "en_150",
+ "en_SL": "en_001",
+ "en_SS": "en_001",
+ "en_SX": "en_001",
+ "en_SZ": "en_001",
+ "en_TC": "en_001",
+ "en_TK": "en_001",
+ "en_TO": "en_001",
+ "en_TT": "en_001",
+ "en_TV": "en_001",
+ "en_TZ": "en_001",
+ "en_UG": "en_001",
+ "en_VC": "en_001",
+ "en_VG": "en_001",
+ "en_VU": "en_001",
+ "en_WS": "en_001",
+ "en_ZA": "en_001",
+ "en_ZM": "en_001",
+ "en_ZW": "en_001",
+ "es_AR": "es_419",
+ "es_BO": "es_419",
+ "es_BR": "es_419",
+ "es_BZ": "es_419",
+ "es_CL": "es_419",
+ "es_CO": "es_419",
+ "es_CR": "es_419",
+ "es_CU": "es_419",
+ "es_DO": "es_419",
+ "es_EC": "es_419",
+ "es_GT": "es_419",
+ "es_HN": "es_419",
+ "es_MX": "es_419",
+ "es_NI": "es_419",
+ "es_PA": "es_419",
+ "es_PE": "es_419",
+ "es_PR": "es_419",
+ "es_PY": "es_419",
+ "es_SV": "es_419",
+ "es_US": "es_419",
+ "es_UY": "es_419",
+ "es_VE": "es_419",
+ "ff_Adlm": "root",
+ "nb": "no",
+ "nn": "no",
+ "pa_Arab": "root",
+ "pt_AO": "pt_PT",
+ "pt_CH": "pt_PT",
+ "pt_CV": "pt_PT",
+ "pt_GQ": "pt_PT",
+ "pt_GW": "pt_PT",
+ "pt_LU": "pt_PT",
+ "pt_MO": "pt_PT",
+ "pt_MZ": "pt_PT",
+ "pt_ST": "pt_PT",
+ "pt_TL": "pt_PT",
+ "sd_Deva": "root",
+ "sr_Latn": "root",
+ "uz_Arab": "root",
+ "uz_Cyrl": "root",
+ "zh_Hant": "root",
+ "zh_Hant_MO": "zh_Hant_HK"
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/functions.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/functions.php
new file mode 100644
index 0000000..901d2f8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/functions.php
@@ -0,0 +1,22 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+if (!\function_exists(t::class)) {
+ /**
+ * @author Nate Wiebe <nate@northern.co>
+ */
+ function t(string $message, array $parameters = [], string $domain = null): TranslatableMessage
+ {
+ return new TranslatableMessage($message, $parameters, $domain);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/schemas/xliff-core-1.2-strict.xsd b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/schemas/xliff-core-1.2-strict.xsd
new file mode 100644
index 0000000..dface62
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/schemas/xliff-core-1.2-strict.xsd
@@ -0,0 +1,2223 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+
+May-19-2004:
+- Changed the <choice> for ElemType_header, moving minOccurs="0" maxOccurs="unbounded" from its elements
+to <choice> itself.
+- Added <choice> for ElemType_trans-unit to allow "any order" for <context-group>, <count-group>, <prop-group>, <note>, and
+<alt-trans>.
+
+Oct-2005
+- updated version info to 1.2
+- equiv-trans attribute to <trans-unit> element
+- merged-trans attribute for <group> element
+- Add the <seg-source> element as optional in the <trans-unit> and <alt-trans> content models, at the same level as <source>
+- Create a new value "seg" for the mtype attribute of the <mrk> element
+- Add mid as an optional attribute for the <alt-trans> element
+
+Nov-14-2005
+- Changed name attribute for <context-group> from required to optional
+- Added extension point at <xliff>
+
+Jan-9-2006
+- Added alttranstype type attribute to <alt-trans>, and values
+
+Jan-10-2006
+- Corrected error with overwritten purposeValueList
+- Corrected name="AttrType_Version", attribute should have been "name"
+
+-->
+<xsd:schema xmlns:xlf="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="urn:oasis:names:tc:xliff:document:1.2" xml:lang="en">
+ <!-- Import for xml:lang and xml:space -->
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+ <!-- Attributes Lists -->
+ <xsd:simpleType name="XTend">
+ <xsd:restriction base="xsd:string">
+ <xsd:pattern value="x-[^\s]+"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="context-typeValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'context-type'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="database">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a database content.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="element">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the content of an element within an XML document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="elementtitle">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the name of an element within an XML document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="linenumber">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the line number from the sourcefile (see context-type="sourcefile") where the <source> is found.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="numparams">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a the number of parameters contained within the <source>.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="paramnotes">
+ <xsd:annotation>
+ <xsd:documentation>Indicates notes pertaining to the parameters in the <source>.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="record">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the content of a record within a database.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="recordtitle">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the name of a record within a database.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="sourcefile">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the original source file in the case that multiple files are merged to form the original file from which the XLIFF file is created. This differs from the original <file> attribute in that this sourcefile is one of many that make up that file.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="count-typeValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'count-type'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="num-usages">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the count units are items that are used X times in a certain context; example: this is a reusable text unit which is used 42 times in other texts.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="repetition">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the count units are translation units existing already in the same document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="total">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a total count.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="InlineDelimitersValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'ctype' when used other elements than <ph> or <x>.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="bold">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a run of bolded text.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="italic">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a run of text in italics.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="underlined">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a run of underlined text.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="link">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a run of hyper-text.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="InlinePlaceholdersValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'ctype' when used with <ph> or <x>.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="image">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a inline image.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pb">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a page break.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="lb">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a line break.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="mime-typeValueList">
+ <xsd:restriction base="xsd:string">
+ <xsd:pattern value="(text|multipart|message|application|image|audio|video|model)(/.+)*"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="datatypeValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'datatype'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="asp">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Active Server Page data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="c">
+ <xsd:annotation>
+ <xsd:documentation>Indicates C source file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cdf">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Channel Definition Format (CDF) data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cfm">
+ <xsd:annotation>
+ <xsd:documentation>Indicates ColdFusion data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cpp">
+ <xsd:annotation>
+ <xsd:documentation>Indicates C++ source file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="csharp">
+ <xsd:annotation>
+ <xsd:documentation>Indicates C-Sharp data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cstring">
+ <xsd:annotation>
+ <xsd:documentation>Indicates strings from C, ASM, and driver files data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="csv">
+ <xsd:annotation>
+ <xsd:documentation>Indicates comma-separated values data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="database">
+ <xsd:annotation>
+ <xsd:documentation>Indicates database data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="documentfooter">
+ <xsd:annotation>
+ <xsd:documentation>Indicates portions of document that follows data and contains metadata.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="documentheader">
+ <xsd:annotation>
+ <xsd:documentation>Indicates portions of document that precedes data and contains metadata.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="filedialog">
+ <xsd:annotation>
+ <xsd:documentation>Indicates data from standard UI file operations dialogs (e.g., Open, Save, Save As, Export, Import).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="form">
+ <xsd:annotation>
+ <xsd:documentation>Indicates standard user input screen data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="html">
+ <xsd:annotation>
+ <xsd:documentation>Indicates HyperText Markup Language (HTML) data - document instance.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="htmlbody">
+ <xsd:annotation>
+ <xsd:documentation>Indicates content within an HTML document’s <body> element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="ini">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Windows INI file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="interleaf">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Interleaf data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="javaclass">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Java source file data (extension '.java').</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="javapropertyresourcebundle">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Java property resource bundle data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="javalistresourcebundle">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Java list resource bundle data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="javascript">
+ <xsd:annotation>
+ <xsd:documentation>Indicates JavaScript source file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="jscript">
+ <xsd:annotation>
+ <xsd:documentation>Indicates JScript source file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="layout">
+ <xsd:annotation>
+ <xsd:documentation>Indicates information relating to formatting.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="lisp">
+ <xsd:annotation>
+ <xsd:documentation>Indicates LISP source file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="margin">
+ <xsd:annotation>
+ <xsd:documentation>Indicates information relating to margin formats.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="menufile">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a file containing menu.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="messagefile">
+ <xsd:annotation>
+ <xsd:documentation>Indicates numerically identified string table.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="mif">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Maker Interchange Format (MIF) data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="mimetype">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the datatype attribute value is a MIME Type value and is defined in the mime-type attribute.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="mo">
+ <xsd:annotation>
+ <xsd:documentation>Indicates GNU Machine Object data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="msglib">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Message Librarian strings created by Novell's Message Librarian Tool.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pagefooter">
+ <xsd:annotation>
+ <xsd:documentation>Indicates information to be displayed at the bottom of each page of a document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pageheader">
+ <xsd:annotation>
+ <xsd:documentation>Indicates information to be displayed at the top of each page of a document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="parameters">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a list of property values (e.g., settings within INI files or preferences dialog).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pascal">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Pascal source file data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="php">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Hypertext Preprocessor data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="plaintext">
+ <xsd:annotation>
+ <xsd:documentation>Indicates plain text file (no formatting other than, possibly, wrapping).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="po">
+ <xsd:annotation>
+ <xsd:documentation>Indicates GNU Portable Object file.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="report">
+ <xsd:annotation>
+ <xsd:documentation>Indicates dynamically generated user defined document. e.g. Oracle Report, Crystal Report, etc.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="resources">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Windows .NET binary resources.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="resx">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Windows .NET Resources.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rtf">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Rich Text Format (RTF) data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="sgml">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Standard Generalized Markup Language (SGML) data - document instance.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="sgmldtd">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Standard Generalized Markup Language (SGML) data - Document Type Definition (DTD).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="svg">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Scalable Vector Graphic (SVG) data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="vbscript">
+ <xsd:annotation>
+ <xsd:documentation>Indicates VisualBasic Script source file.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="warning">
+ <xsd:annotation>
+ <xsd:documentation>Indicates warning message.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="winres">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Windows (Win32) resources (i.e. resources extracted from an RC script, a message file, or a compiled file).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="xhtml">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Extensible HyperText Markup Language (XHTML) data - document instance.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="xml">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Extensible Markup Language (XML) data - document instance.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="xmldtd">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Extensible Markup Language (XML) data - Document Type Definition (DTD).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="xsl">
+ <xsd:annotation>
+ <xsd:documentation>Indicates Extensible Stylesheet Language (XSL) data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="xul">
+ <xsd:annotation>
+ <xsd:documentation>Indicates XUL elements.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="mtypeValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'mtype'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="abbrev">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the marked text is an abbreviation.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="abbreviated-form">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.8: A term resulting from the omission of any part of the full term while designating the same concept.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="abbreviation">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.8.1: An abbreviated form of a simple term resulting from the omission of some of its letters (e.g. 'adj.' for 'adjective').</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="acronym">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.8.4: An abbreviated form of a term made up of letters from the full form of a multiword term strung together into a sequence pronounced only syllabically (e.g. 'radar' for 'radio detecting and ranging').</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="appellation">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620: A proper-name term, such as the name of an agency or other proper entity.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="collocation">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.18.1: A recurrent word combination characterized by cohesion in that the components of the collocation must co-occur within an utterance or series of utterances, even though they do not necessarily have to maintain immediate proximity to one another.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="common-name">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.5: A synonym for an international scientific term that is used in general discourse in a given language.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="datetime">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the marked text is a date and/or time.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="equation">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.15: An expression used to represent a concept based on a statement that two mathematical expressions are, for instance, equal as identified by the equal sign (=), or assigned to one another by a similar sign.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="expanded-form">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.7: The complete representation of a term for which there is an abbreviated form.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="formula">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.14: Figures, symbols or the like used to express a concept briefly, such as a mathematical or chemical formula.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="head-term">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.1: The concept designation that has been chosen to head a terminological record.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="initialism">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.8.3: An abbreviated form of a term consisting of some of the initial letters of the words making up a multiword term or the term elements making up a compound term when these letters are pronounced individually (e.g. 'BSE' for 'bovine spongiform encephalopathy').</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="international-scientific-term">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.4: A term that is part of an international scientific nomenclature as adopted by an appropriate scientific body.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="internationalism">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.6: A term that has the same or nearly identical orthographic or phonemic form in many languages.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="logical-expression">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.16: An expression used to represent a concept based on mathematical or logical relations, such as statements of inequality, set relationships, Boolean operations, and the like.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="materials-management-unit">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.17: A unit to track object.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="name">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the marked text is a name.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="near-synonym">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.3: A term that represents the same or a very similar concept as another term in the same language, but for which interchangeability is limited to some contexts and inapplicable in others.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="part-number">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.17.2: A unique alphanumeric designation assigned to an object in a manufacturing system.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="phrase">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the marked text is a phrase.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="phraseological-unit">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.18: Any group of two or more words that form a unit, the meaning of which frequently cannot be deduced based on the combined sense of the words making up the phrase.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="protected">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the marked text should not be translated.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="romanized-form">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.12: A form of a term resulting from an operation whereby non-Latin writing systems are converted to the Latin alphabet.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="seg">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the marked text represents a segment.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="set-phrase">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.18.2: A fixed, lexicalized phrase.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="short-form">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.8.2: A variant of a multiword term that includes fewer words than the full form of the term (e.g. 'Group of Twenty-four' for 'Intergovernmental Group of Twenty-four on International Monetary Affairs').</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="sku">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.17.1: Stock keeping unit, an inventory item identified by a unique alphanumeric designation assigned to an object in an inventory control system.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="standard-text">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.19: A fixed chunk of recurring text.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="symbol">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.13: A designation of a concept by letters, numerals, pictograms or any combination thereof.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="synonym">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.2: Any term that represents the same or a very similar concept as the main entry term in a term entry.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="synonymous-phrase">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.18.3: Phraseological unit in a language that expresses the same semantic content as another phrase in that same language.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="term">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the marked text is a term.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="transcribed-form">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.11: A form of a term resulting from an operation whereby the characters of one writing system are represented by characters from another writing system, taking into account the pronunciation of the characters converted.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="transliterated-form">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.10: A form of a term resulting from an operation whereby the characters of an alphabetic writing system are represented by characters from another alphabetic writing system.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="truncated-term">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.8.5: An abbreviated form of a term resulting from the omission of one or more term elements or syllables (e.g. 'flu' for 'influenza').</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="variant">
+ <xsd:annotation>
+ <xsd:documentation>ISO-12620 2.1.9: One of the alternate forms of a term.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="restypeValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'restype'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="auto3state">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC AUTO3STATE control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="autocheckbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC AUTOCHECKBOX control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="autoradiobutton">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC AUTORADIOBUTTON control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="bedit">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC BEDIT control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="bitmap">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a bitmap, for example a BITMAP resource in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="button">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a button object, for example a BUTTON control Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="caption">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a caption, such as the caption of a dialog box.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cell">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the cell in a table, for example the content of the <td> element in HTML.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="checkbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates check box object, for example a CHECKBOX control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="checkboxmenuitem">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a menu item with an associated checkbox.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="checkedlistbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a list box, but with a check-box for each item.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="colorchooser">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a color selection dialog.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="combobox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a combination of edit box and listbox object, for example a COMBOBOX control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="comboboxexitem">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an initialization entry of an extended combobox DLGINIT resource block. (code 0x1234).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="comboboxitem">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an initialization entry of a combobox DLGINIT resource block (code 0x0403).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="component">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a UI base class element that cannot be represented by any other element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="contextmenu">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a context menu.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="ctext">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC CTEXT control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cursor">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a cursor, for example a CURSOR resource in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="datetimepicker">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a date/time picker.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="defpushbutton">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC DEFPUSHBUTTON control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="dialog">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a dialog box.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="dlginit">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC DLGINIT resource block.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="edit">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an edit box object, for example an EDIT control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="file">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a filename.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="filechooser">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a file dialog.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="fn">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a footnote.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="font">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a font name.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="footer">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a footer.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="frame">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a frame object.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="grid">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a XUL grid element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="groupbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a groupbox object, for example a GROUPBOX control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="header">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a header item.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="heading">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a heading, such has the content of <h1>, <h2>, etc. in HTML.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="hedit">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC HEDIT control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="hscrollbar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a horizontal scrollbar.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="icon">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an icon, for example an ICON resource in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="iedit">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC IEDIT control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="keywords">
+ <xsd:annotation>
+ <xsd:documentation>Indicates keyword list, such as the content of the Keywords meta-data in HTML, or a K footnote in WinHelp RTF.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="label">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a label object.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="linklabel">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a label that is also a HTML link (not necessarily a URL).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="list">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a list (a group of list-items, for example an <ol> or <ul> element in HTML).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="listbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a listbox object, for example an LISTBOX control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="listitem">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an list item (an entry in a list).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="ltext">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC LTEXT control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="menu">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a menu (a group of menu-items).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="menubar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a toolbar containing one or more tope level menus.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="menuitem">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a menu item (an entry in a menu).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="menuseparator">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a XUL menuseparator element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="message">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a message, for example an entry in a MESSAGETABLE resource in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="monthcalendar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a calendar control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="numericupdown">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an edit box beside a spin control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="panel">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a catch all for rectangular areas.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="popupmenu">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a standalone menu not necessarily associated with a menubar.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pushbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a pushbox object, for example a PUSHBOX control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pushbutton">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC PUSHBUTTON control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="radio">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a radio button object.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="radiobuttonmenuitem">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a menuitem with associated radio button.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rcdata">
+ <xsd:annotation>
+ <xsd:documentation>Indicates raw data resources for an application.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="row">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a row in a table.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rtext">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC RTEXT control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="scrollpane">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a user navigable container used to show a portion of a document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="separator">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a generic divider object (e.g. menu group separator).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="shortcut">
+ <xsd:annotation>
+ <xsd:documentation>Windows accelerators, shortcuts in resource or property files.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="spinner">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a UI control to indicate process activity but not progress.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="splitter">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a splitter bar.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="state3">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC STATE3 control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="statusbar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a window for providing feedback to the users, like 'read-only', etc.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="string">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a string, for example an entry in a STRINGTABLE resource in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="tabcontrol">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a layers of controls with a tab to select layers.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="table">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a display and edits regular two-dimensional tables of cells.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="textbox">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a XUL textbox element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="togglebutton">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a UI button that can be toggled to on or off state.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="toolbar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an array of controls, usually buttons.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="tooltip">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a pop up tool tip text.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="trackbar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a bar with a pointer indicating a position within a certain range.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="tree">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a control that displays a set of hierarchical data.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="uri">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a URI (URN or URL).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="userbutton">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a Windows RC USERBUTTON control.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="usercontrol">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a user-defined control like CONTROL control in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="var">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the text of a variable.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="versioninfo">
+ <xsd:annotation>
+ <xsd:documentation>Indicates version information about a resource like VERSIONINFO in Windows.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="vscrollbar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a vertical scrollbar.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="window">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a graphical window.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="size-unitValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'size-unit'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="byte">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in 8-bit bytes.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="char">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in Unicode characters.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="col">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in columns. Used for HTML text area.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="cm">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in centimeters.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="dlgunit">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in dialog units, as defined in Windows resources.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="em">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in 'font-size' units (as defined in CSS).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="ex">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in 'x-height' units (as defined in CSS).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="glyph">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in glyphs. A glyph is considered to be one or more combined Unicode characters that represent a single displayable text character. Sometimes referred to as a 'grapheme cluster'</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="in">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in inches.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="mm">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in millimeters.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="percent">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in percentage.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="pixel">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in pixels.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="point">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in point.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="row">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a size in rows. Used for HTML text area.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="stateValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'state'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="final">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the terminating state.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="needs-adaptation">
+ <xsd:annotation>
+ <xsd:documentation>Indicates only non-textual information needs adaptation.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="needs-l10n">
+ <xsd:annotation>
+ <xsd:documentation>Indicates both text and non-textual information needs adaptation.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="needs-review-adaptation">
+ <xsd:annotation>
+ <xsd:documentation>Indicates only non-textual information needs review.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="needs-review-l10n">
+ <xsd:annotation>
+ <xsd:documentation>Indicates both text and non-textual information needs review.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="needs-review-translation">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that only the text of the item needs to be reviewed.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="needs-translation">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item needs to be translated.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="new">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item is new. For example, translation units that were not in a previous version of the document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="signed-off">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that changes are reviewed and approved.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="translated">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item has been translated.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="state-qualifierValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'state-qualifier'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="exact-match">
+ <xsd:annotation>
+ <xsd:documentation>Indicates an exact match. An exact match occurs when a source text of a segment is exactly the same as the source text of a segment that was translated previously.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="fuzzy-match">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a fuzzy match. A fuzzy match occurs when a source text of a segment is very similar to the source text of a segment that was translated previously (e.g. when the difference is casing, a few changed words, white-space discripancy, etc.).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="id-match">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a match based on matching IDs (in addition to matching text).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="leveraged-glossary">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a translation derived from a glossary.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="leveraged-inherited">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a translation derived from existing translation.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="leveraged-mt">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a translation derived from machine translation.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="leveraged-repository">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a translation derived from a translation repository.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="leveraged-tm">
+ <xsd:annotation>
+ <xsd:documentation>Indicates a translation derived from a translation memory.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="mt-suggestion">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the translation is suggested by machine translation.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rejected-grammar">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item has been rejected because of incorrect grammar.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rejected-inaccurate">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item has been rejected because it is incorrect.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rejected-length">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item has been rejected because it is too long or too short.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rejected-spelling">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the item has been rejected because of incorrect spelling.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="tm-suggestion">
+ <xsd:annotation>
+ <xsd:documentation>Indicates the translation is suggested by translation memory.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="unitValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'unit'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="word">
+ <xsd:annotation>
+ <xsd:documentation>Refers to words.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="page">
+ <xsd:annotation>
+ <xsd:documentation>Refers to pages.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="trans-unit">
+ <xsd:annotation>
+ <xsd:documentation>Refers to <trans-unit> elements.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="bin-unit">
+ <xsd:annotation>
+ <xsd:documentation>Refers to <bin-unit> elements.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="glyph">
+ <xsd:annotation>
+ <xsd:documentation>Refers to glyphs.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="item">
+ <xsd:annotation>
+ <xsd:documentation>Refers to <trans-unit> and/or <bin-unit> elements.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="instance">
+ <xsd:annotation>
+ <xsd:documentation>Refers to the occurrences of instances defined by the count-type value.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="character">
+ <xsd:annotation>
+ <xsd:documentation>Refers to characters.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="line">
+ <xsd:annotation>
+ <xsd:documentation>Refers to lines.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="sentence">
+ <xsd:annotation>
+ <xsd:documentation>Refers to sentences.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="paragraph">
+ <xsd:annotation>
+ <xsd:documentation>Refers to paragraphs.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="segment">
+ <xsd:annotation>
+ <xsd:documentation>Refers to segments.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="placeable">
+ <xsd:annotation>
+ <xsd:documentation>Refers to placeables (inline elements).</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="priorityValueList">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'priority'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:positiveInteger">
+ <xsd:enumeration value="1">
+ <xsd:annotation>
+ <xsd:documentation>Highest priority.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="2">
+ <xsd:annotation>
+ <xsd:documentation>High priority.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="3">
+ <xsd:annotation>
+ <xsd:documentation>High priority, but not as important as 2.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="4">
+ <xsd:annotation>
+ <xsd:documentation>High priority, but not as important as 3.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="5">
+ <xsd:annotation>
+ <xsd:documentation>Medium priority, but more important than 6.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="6">
+ <xsd:annotation>
+ <xsd:documentation>Medium priority, but less important than 5.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="7">
+ <xsd:annotation>
+ <xsd:documentation>Low priority, but more important than 8.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="8">
+ <xsd:annotation>
+ <xsd:documentation>Low priority, but more important than 9.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="9">
+ <xsd:annotation>
+ <xsd:documentation>Low priority.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="10">
+ <xsd:annotation>
+ <xsd:documentation>Lowest priority.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="reformatValueYesNo">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="yes">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that all properties can be reformatted. This value must be used alone.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="no">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that no properties should be reformatted. This value must be used alone.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="reformatValueList">
+ <xsd:list>
+ <xsd:simpleType>
+ <xsd:union memberTypes="xlf:XTend">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="coord">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that all information in the coord attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="coord-x">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the x information in the coord attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="coord-y">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the y information in the coord attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="coord-cx">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the cx information in the coord attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="coord-cy">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the cy information in the coord attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="font">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that all the information in the font attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="font-name">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the name information in the font attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="font-size">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the size information in the font attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="font-weight">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the weight information in the font attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="css-style">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the information in the css-style attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="style">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the information in the style attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="ex-style">
+ <xsd:annotation>
+ <xsd:documentation>This value indicates that the information in the exstyle attribute can be modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:union>
+ </xsd:simpleType>
+ </xsd:list>
+ </xsd:simpleType>
+ <xsd:simpleType name="purposeValueList">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="information">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the context is informational in nature, specifying for example, how a term should be translated. Thus, should be displayed to anyone editing the XLIFF document.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="location">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the context-group is used to specify where the term was found in the translatable source. Thus, it is not displayed.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="match">
+ <xsd:annotation>
+ <xsd:documentation>Indicates that the context information should be used during translation memory lookups. Thus, it is not displayed.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="alttranstypeValueList">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="proposal">
+ <xsd:annotation>
+ <xsd:documentation>Represents a translation proposal from a translation memory or other resource.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="previous-version">
+ <xsd:annotation>
+ <xsd:documentation>Represents a previous version of the target element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="rejected">
+ <xsd:annotation>
+ <xsd:documentation>Represents a rejected version of the target element.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="reference">
+ <xsd:annotation>
+ <xsd:documentation>Represents a translation to be used for reference purposes only, for example from a related product or a different language.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ <xsd:enumeration value="accepted">
+ <xsd:annotation>
+ <xsd:documentation>Represents a proposed translation that was used for the translation of the trans-unit, possibly modified.</xsd:documentation>
+ </xsd:annotation>
+ </xsd:enumeration>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <!-- Other Types -->
+ <xsd:complexType name="ElemType_ExternalReference">
+ <xsd:choice>
+ <xsd:element ref="xlf:internal-file"/>
+ <xsd:element ref="xlf:external-file"/>
+ </xsd:choice>
+ </xsd:complexType>
+ <xsd:simpleType name="AttrType_purpose">
+ <xsd:list>
+ <xsd:simpleType>
+ <xsd:union memberTypes="xlf:purposeValueList xlf:XTend"/>
+ </xsd:simpleType>
+ </xsd:list>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_datatype">
+ <xsd:union memberTypes="xlf:datatypeValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_restype">
+ <xsd:union memberTypes="xlf:restypeValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_alttranstype">
+ <xsd:union memberTypes="xlf:alttranstypeValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_context-type">
+ <xsd:union memberTypes="xlf:context-typeValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_state">
+ <xsd:union memberTypes="xlf:stateValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_state-qualifier">
+ <xsd:union memberTypes="xlf:state-qualifierValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_count-type">
+ <xsd:union memberTypes="xlf:restypeValueList xlf:count-typeValueList xlf:datatypeValueList xlf:stateValueList xlf:state-qualifierValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_InlineDelimiters">
+ <xsd:union memberTypes="xlf:InlineDelimitersValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_InlinePlaceholders">
+ <xsd:union memberTypes="xlf:InlinePlaceholdersValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_size-unit">
+ <xsd:union memberTypes="xlf:size-unitValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_mtype">
+ <xsd:union memberTypes="xlf:mtypeValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_unit">
+ <xsd:union memberTypes="xlf:unitValueList xlf:XTend"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_priority">
+ <xsd:union memberTypes="xlf:priorityValueList"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_reformat">
+ <xsd:union memberTypes="xlf:reformatValueYesNo xlf:reformatValueList"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_YesNo">
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="yes"/>
+ <xsd:enumeration value="no"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_Position">
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="open"/>
+ <xsd:enumeration value="close"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_assoc">
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="preceding"/>
+ <xsd:enumeration value="following"/>
+ <xsd:enumeration value="both"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_annotates">
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="source"/>
+ <xsd:enumeration value="target"/>
+ <xsd:enumeration value="general"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_Coordinates">
+ <xsd:annotation>
+ <xsd:documentation>Values for the attribute 'coord'.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ <xsd:pattern value="(-?\d+|#);(-?\d+|#);(-?\d+|#);(-?\d+|#)"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="AttrType_Version">
+ <xsd:annotation>
+ <xsd:documentation>Version values: 1.0 and 1.1 are allowed for backward compatibility.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="1.2"/>
+ <xsd:enumeration value="1.1"/>
+ <xsd:enumeration value="1.0"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <!-- Groups -->
+ <xsd:group name="ElemGroup_TextContent">
+ <xsd:choice>
+ <xsd:element ref="xlf:g"/>
+ <xsd:element ref="xlf:bpt"/>
+ <xsd:element ref="xlf:ept"/>
+ <xsd:element ref="xlf:ph"/>
+ <xsd:element ref="xlf:it"/>
+ <xsd:element ref="xlf:mrk"/>
+ <xsd:element ref="xlf:x"/>
+ <xsd:element ref="xlf:bx"/>
+ <xsd:element ref="xlf:ex"/>
+ </xsd:choice>
+ </xsd:group>
+ <xsd:attributeGroup name="AttrGroup_TextContent">
+ <xsd:attribute name="id" type="xsd:string" use="required"/>
+ <xsd:attribute name="xid" type="xsd:string" use="optional"/>
+ <xsd:attribute name="equiv-text" type="xsd:string" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:attributeGroup>
+ <!-- XLIFF Structure -->
+ <xsd:element name="xliff">
+ <xsd:complexType>
+ <xsd:sequence maxOccurs="unbounded">
+ <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
+ <xsd:element ref="xlf:file"/>
+ </xsd:sequence>
+ <xsd:attribute name="version" type="xlf:AttrType_Version" use="required"/>
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="file">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element minOccurs="0" ref="xlf:header"/>
+ <xsd:element ref="xlf:body"/>
+ </xsd:sequence>
+ <xsd:attribute name="original" type="xsd:string" use="required"/>
+ <xsd:attribute name="source-language" type="xsd:language" use="required"/>
+ <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="required"/>
+ <xsd:attribute name="tool-id" type="xsd:string" use="optional"/>
+ <xsd:attribute name="date" type="xsd:dateTime" use="optional"/>
+ <xsd:attribute ref="xml:space" use="optional"/>
+ <xsd:attribute name="category" type="xsd:string" use="optional"/>
+ <xsd:attribute name="target-language" type="xsd:language" use="optional"/>
+ <xsd:attribute name="product-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="product-version" type="xsd:string" use="optional"/>
+ <xsd:attribute name="build-num" type="xsd:string" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ <xsd:unique name="U_group_id">
+ <xsd:selector xpath=".//xlf:group"/>
+ <xsd:field xpath="@id"/>
+ </xsd:unique>
+ <xsd:key name="K_unit_id">
+ <xsd:selector xpath=".//xlf:trans-unit|.//xlf:bin-unit"/>
+ <xsd:field xpath="@id"/>
+ </xsd:key>
+ <xsd:keyref name="KR_unit_id" refer="xlf:K_unit_id">
+ <xsd:selector xpath=".//bpt|.//ept|.//it|.//ph|.//g|.//x|.//bx|.//ex|.//sub"/>
+ <xsd:field xpath="@xid"/>
+ </xsd:keyref>
+ <xsd:key name="K_tool-id">
+ <xsd:selector xpath="xlf:header/xlf:tool"/>
+ <xsd:field xpath="@tool-id"/>
+ </xsd:key>
+ <xsd:keyref name="KR_file_tool-id" refer="xlf:K_tool-id">
+ <xsd:selector xpath="."/>
+ <xsd:field xpath="@tool-id"/>
+ </xsd:keyref>
+ <xsd:keyref name="KR_phase_tool-id" refer="xlf:K_tool-id">
+ <xsd:selector xpath="xlf:header/xlf:phase-group/xlf:phase"/>
+ <xsd:field xpath="@tool-id"/>
+ </xsd:keyref>
+ <xsd:keyref name="KR_alt-trans_tool-id" refer="xlf:K_tool-id">
+ <xsd:selector xpath=".//xlf:trans-unit/xlf:alt-trans"/>
+ <xsd:field xpath="@tool-id"/>
+ </xsd:keyref>
+ <xsd:key name="K_count-group_name">
+ <xsd:selector xpath=".//xlf:count-group"/>
+ <xsd:field xpath="@name"/>
+ </xsd:key>
+ <xsd:unique name="U_context-group_name">
+ <xsd:selector xpath=".//xlf:context-group"/>
+ <xsd:field xpath="@name"/>
+ </xsd:unique>
+ <xsd:key name="K_phase-name">
+ <xsd:selector xpath="xlf:header/xlf:phase-group/xlf:phase"/>
+ <xsd:field xpath="@phase-name"/>
+ </xsd:key>
+ <xsd:keyref name="KR_phase-name" refer="xlf:K_phase-name">
+ <xsd:selector xpath=".//xlf:count|.//xlf:trans-unit|.//xlf:target|.//bin-unit|.//bin-target"/>
+ <xsd:field xpath="@phase-name"/>
+ </xsd:keyref>
+ <xsd:unique name="U_uid">
+ <xsd:selector xpath=".//xlf:external-file"/>
+ <xsd:field xpath="@uid"/>
+ </xsd:unique>
+ </xsd:element>
+ <xsd:element name="header">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element minOccurs="0" name="skl" type="xlf:ElemType_ExternalReference"/>
+ <xsd:element minOccurs="0" ref="xlf:phase-group"/>
+ <xsd:choice maxOccurs="unbounded" minOccurs="0">
+ <xsd:element name="glossary" type="xlf:ElemType_ExternalReference"/>
+ <xsd:element name="reference" type="xlf:ElemType_ExternalReference"/>
+ <xsd:element ref="xlf:count-group"/>
+ <xsd:element ref="xlf:note"/>
+ <xsd:element ref="xlf:tool"/>
+ </xsd:choice>
+ <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="internal-file">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="form" type="xsd:string"/>
+ <xsd:attribute name="crc" type="xsd:NMTOKEN"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="external-file">
+ <xsd:complexType>
+ <xsd:attribute name="href" type="xsd:string" use="required"/>
+ <xsd:attribute name="crc" type="xsd:NMTOKEN"/>
+ <xsd:attribute name="uid" type="xsd:NMTOKEN"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="note">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ <xsd:attribute default="1" name="priority" type="xlf:AttrType_priority" use="optional"/>
+ <xsd:attribute name="from" type="xsd:string" use="optional"/>
+ <xsd:attribute default="general" name="annotates" type="xlf:AttrType_annotates" use="optional"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="phase-group">
+ <xsd:complexType>
+ <xsd:sequence maxOccurs="unbounded">
+ <xsd:element ref="xlf:phase"/>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="phase">
+ <xsd:complexType>
+ <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:note"/>
+ </xsd:sequence>
+ <xsd:attribute name="phase-name" type="xsd:string" use="required"/>
+ <xsd:attribute name="process-name" type="xsd:string" use="required"/>
+ <xsd:attribute name="company-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="tool-id" type="xsd:string" use="optional"/>
+ <xsd:attribute name="date" type="xsd:dateTime" use="optional"/>
+ <xsd:attribute name="job-id" type="xsd:string" use="optional"/>
+ <xsd:attribute name="contact-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="contact-email" type="xsd:string" use="optional"/>
+ <xsd:attribute name="contact-phone" type="xsd:string" use="optional"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="count-group">
+ <xsd:complexType>
+ <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:count"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="count">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="count-type" type="xlf:AttrType_count-type" use="optional"/>
+ <xsd:attribute name="phase-name" type="xsd:string" use="optional"/>
+ <xsd:attribute default="word" name="unit" type="xlf:AttrType_unit" use="optional"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="context-group">
+ <xsd:complexType>
+ <xsd:sequence maxOccurs="unbounded">
+ <xsd:element ref="xlf:context"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="purpose" type="xlf:AttrType_purpose" use="optional"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="context">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="context-type" type="xlf:AttrType_context-type" use="required"/>
+ <xsd:attribute default="no" name="match-mandatory" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:NMTOKEN" use="optional"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="tool">
+ <xsd:complexType mixed="true">
+ <xsd:sequence>
+ <xsd:any namespace="##any" processContents="strict" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="tool-id" type="xsd:string" use="required"/>
+ <xsd:attribute name="tool-name" type="xsd:string" use="required"/>
+ <xsd:attribute name="tool-version" type="xsd:string" use="optional"/>
+ <xsd:attribute name="tool-company" type="xsd:string" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="body">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded" minOccurs="0">
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:group"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:trans-unit"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:bin-unit"/>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="group">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:sequence>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:context-group"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:count-group"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:note"/>
+ <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
+ </xsd:sequence>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:group"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:trans-unit"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:bin-unit"/>
+ </xsd:choice>
+ </xsd:sequence>
+ <xsd:attribute name="id" type="xsd:string" use="optional"/>
+ <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
+ <xsd:attribute default="default" ref="xml:space" use="optional"/>
+ <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
+ <xsd:attribute name="resname" type="xsd:string" use="optional"/>
+ <xsd:attribute name="extradata" type="xsd:string" use="optional"/>
+ <xsd:attribute name="extype" type="xsd:string" use="optional"/>
+ <xsd:attribute name="help-id" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="menu" type="xsd:string" use="optional"/>
+ <xsd:attribute name="menu-option" type="xsd:string" use="optional"/>
+ <xsd:attribute name="menu-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
+ <xsd:attribute name="font" type="xsd:string" use="optional"/>
+ <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
+ <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute default="yes" name="translate" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attribute default="yes" name="reformat" type="xlf:AttrType_reformat" use="optional"/>
+ <xsd:attribute default="pixel" name="size-unit" type="xlf:AttrType_size-unit" use="optional"/>
+ <xsd:attribute name="maxwidth" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="minwidth" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="maxheight" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="minheight" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="maxbytes" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="minbytes" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="charclass" type="xsd:string" use="optional"/>
+ <xsd:attribute default="no" name="merged-trans" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="trans-unit">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="xlf:source"/>
+ <xsd:element minOccurs="0" ref="xlf:seg-source"/>
+ <xsd:element minOccurs="0" ref="xlf:target"/>
+ <xsd:choice maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:context-group"/>
+ <xsd:element ref="xlf:count-group"/>
+ <xsd:element ref="xlf:note"/>
+ <xsd:element ref="xlf:alt-trans"/>
+ </xsd:choice>
+ <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
+ </xsd:sequence>
+ <xsd:attribute name="id" type="xsd:string" use="required"/>
+ <xsd:attribute name="approved" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attribute default="yes" name="translate" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attribute default="yes" name="reformat" type="xlf:AttrType_reformat" use="optional"/>
+ <xsd:attribute default="default" ref="xml:space" use="optional"/>
+ <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
+ <xsd:attribute name="phase-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
+ <xsd:attribute name="resname" type="xsd:string" use="optional"/>
+ <xsd:attribute name="extradata" type="xsd:string" use="optional"/>
+ <xsd:attribute name="extype" type="xsd:string" use="optional"/>
+ <xsd:attribute name="help-id" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="menu" type="xsd:string" use="optional"/>
+ <xsd:attribute name="menu-option" type="xsd:string" use="optional"/>
+ <xsd:attribute name="menu-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
+ <xsd:attribute name="font" type="xsd:string" use="optional"/>
+ <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
+ <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute default="pixel" name="size-unit" type="xlf:AttrType_size-unit" use="optional"/>
+ <xsd:attribute name="maxwidth" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="minwidth" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="maxheight" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="minheight" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="maxbytes" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="minbytes" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="charclass" type="xsd:string" use="optional"/>
+ <xsd:attribute default="yes" name="merged-trans" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ <xsd:unique name="U_tu_segsrc_mid">
+ <xsd:selector xpath="./xlf:seg-source/xlf:mrk"/>
+ <xsd:field xpath="@mid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_tu_segsrc_mid" refer="xlf:U_tu_segsrc_mid">
+ <xsd:selector xpath="./xlf:target/xlf:mrk|./xlf:alt-trans"/>
+ <xsd:field xpath="@mid"/>
+ </xsd:keyref>
+ </xsd:element>
+ <xsd:element name="source">
+ <xsd:complexType mixed="true">
+ <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ <xsd:unique name="U_source_bpt_rid">
+ <xsd:selector xpath=".//xlf:bpt"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_source_ept_rid" refer="xlf:U_source_bpt_rid">
+ <xsd:selector xpath=".//xlf:ept"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:keyref>
+ <xsd:unique name="U_source_bx_rid">
+ <xsd:selector xpath=".//xlf:bx"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_source_ex_rid" refer="xlf:U_source_bx_rid">
+ <xsd:selector xpath=".//xlf:ex"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:keyref>
+ </xsd:element>
+ <xsd:element name="seg-source">
+ <xsd:complexType mixed="true">
+ <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ <xsd:unique name="U_segsrc_bpt_rid">
+ <xsd:selector xpath=".//xlf:bpt"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_segsrc_ept_rid" refer="xlf:U_segsrc_bpt_rid">
+ <xsd:selector xpath=".//xlf:ept"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:keyref>
+ <xsd:unique name="U_segsrc_bx_rid">
+ <xsd:selector xpath=".//xlf:bx"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_segsrc_ex_rid" refer="xlf:U_segsrc_bx_rid">
+ <xsd:selector xpath=".//xlf:ex"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:keyref>
+ </xsd:element>
+ <xsd:element name="target">
+ <xsd:complexType mixed="true">
+ <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
+ <xsd:attribute name="state" type="xlf:AttrType_state" use="optional"/>
+ <xsd:attribute name="state-qualifier" type="xlf:AttrType_state-qualifier" use="optional"/>
+ <xsd:attribute name="phase-name" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ <xsd:attribute name="resname" type="xsd:string" use="optional"/>
+ <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
+ <xsd:attribute name="font" type="xsd:string" use="optional"/>
+ <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
+ <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute default="yes" name="equiv-trans" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ <xsd:unique name="U_target_bpt_rid">
+ <xsd:selector xpath=".//xlf:bpt"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_target_ept_rid" refer="xlf:U_target_bpt_rid">
+ <xsd:selector xpath=".//xlf:ept"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:keyref>
+ <xsd:unique name="U_target_bx_rid">
+ <xsd:selector xpath=".//xlf:bx"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_target_ex_rid" refer="xlf:U_target_bx_rid">
+ <xsd:selector xpath=".//xlf:ex"/>
+ <xsd:field xpath="@rid"/>
+ </xsd:keyref>
+ </xsd:element>
+ <xsd:element name="alt-trans">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element minOccurs="0" ref="xlf:source"/>
+ <xsd:element minOccurs="0" ref="xlf:seg-source"/>
+ <xsd:element maxOccurs="1" ref="xlf:target"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:context-group"/>
+ <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:note"/>
+ <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
+ </xsd:sequence>
+ <xsd:attribute name="match-quality" type="xsd:string" use="optional"/>
+ <xsd:attribute name="tool-id" type="xsd:string" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute ref="xml:lang" use="optional"/>
+ <xsd:attribute name="origin" type="xsd:string" use="optional"/>
+ <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
+ <xsd:attribute default="default" ref="xml:space" use="optional"/>
+ <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
+ <xsd:attribute name="resname" type="xsd:string" use="optional"/>
+ <xsd:attribute name="extradata" type="xsd:string" use="optional"/>
+ <xsd:attribute name="extype" type="xsd:string" use="optional"/>
+ <xsd:attribute name="help-id" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="menu" type="xsd:string" use="optional"/>
+ <xsd:attribute name="menu-option" type="xsd:string" use="optional"/>
+ <xsd:attribute name="menu-name" type="xsd:string" use="optional"/>
+ <xsd:attribute name="mid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
+ <xsd:attribute name="font" type="xsd:string" use="optional"/>
+ <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
+ <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="phase-name" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute default="proposal" name="alttranstype" type="xlf:AttrType_alttranstype" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ <xsd:unique name="U_at_segsrc_mid">
+ <xsd:selector xpath="./xlf:seg-source/xlf:mrk"/>
+ <xsd:field xpath="@mid"/>
+ </xsd:unique>
+ <xsd:keyref name="KR_at_segsrc_mid" refer="xlf:U_at_segsrc_mid">
+ <xsd:selector xpath="./xlf:target/xlf:mrk"/>
+ <xsd:field xpath="@mid"/>
+ </xsd:keyref>
+ </xsd:element>
+ <xsd:element name="bin-unit">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="xlf:bin-source"/>
+ <xsd:element minOccurs="0" ref="xlf:bin-target"/>
+ <xsd:choice maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:context-group"/>
+ <xsd:element ref="xlf:count-group"/>
+ <xsd:element ref="xlf:note"/>
+ <xsd:element ref="xlf:trans-unit"/>
+ </xsd:choice>
+ <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
+ </xsd:sequence>
+ <xsd:attribute name="id" type="xsd:string" use="required"/>
+ <xsd:attribute name="mime-type" type="xlf:mime-typeValueList" use="required"/>
+ <xsd:attribute name="approved" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attribute default="yes" name="translate" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attribute default="yes" name="reformat" type="xlf:AttrType_reformat" use="optional"/>
+ <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
+ <xsd:attribute name="resname" type="xsd:string" use="optional"/>
+ <xsd:attribute name="phase-name" type="xsd:string" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="bin-source">
+ <xsd:complexType>
+ <xsd:choice>
+ <xsd:element ref="xlf:internal-file"/>
+ <xsd:element ref="xlf:external-file"/>
+ </xsd:choice>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="bin-target">
+ <xsd:complexType>
+ <xsd:choice>
+ <xsd:element ref="xlf:internal-file"/>
+ <xsd:element ref="xlf:external-file"/>
+ </xsd:choice>
+ <xsd:attribute name="mime-type" type="xlf:mime-typeValueList" use="optional"/>
+ <xsd:attribute name="state" type="xlf:AttrType_state" use="optional"/>
+ <xsd:attribute name="state-qualifier" type="xlf:AttrType_state-qualifier" use="optional"/>
+ <xsd:attribute name="phase-name" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
+ <xsd:attribute name="resname" type="xsd:string" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+ <!-- Element for inline codes -->
+ <xsd:element name="g">
+ <xsd:complexType mixed="true">
+ <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
+ <xsd:attribute default="yes" name="clone" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="x">
+ <xsd:complexType>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlinePlaceholders" use="optional"/>
+ <xsd:attribute default="yes" name="clone" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="bx">
+ <xsd:complexType>
+ <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
+ <xsd:attribute default="yes" name="clone" type="xlf:AttrType_YesNo" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ex">
+ <xsd:complexType>
+ <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ph">
+ <xsd:complexType mixed="true">
+ <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:sub"/>
+ </xsd:sequence>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlinePlaceholders" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:string" use="optional"/>
+ <xsd:attribute name="assoc" type="xlf:AttrType_assoc" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="bpt">
+ <xsd:complexType mixed="true">
+ <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:sub"/>
+ </xsd:sequence>
+ <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:string" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="ept">
+ <xsd:complexType mixed="true">
+ <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:sub"/>
+ </xsd:sequence>
+ <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:string" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="it">
+ <xsd:complexType mixed="true">
+ <xsd:sequence maxOccurs="unbounded" minOccurs="0">
+ <xsd:element ref="xlf:sub"/>
+ </xsd:sequence>
+ <xsd:attribute name="pos" type="xlf:AttrType_Position" use="required"/>
+ <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
+ <xsd:attribute name="crc" type="xsd:string" use="optional"/>
+ <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="sub">
+ <xsd:complexType mixed="true">
+ <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
+ <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
+ <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
+ <xsd:attribute name="xid" type="xsd:string" use="optional"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="mrk">
+ <xsd:complexType mixed="true">
+ <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
+ <xsd:attribute name="mtype" type="xlf:AttrType_mtype" use="required"/>
+ <xsd:attribute name="mid" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="comment" type="xsd:string" use="optional"/>
+ <xsd:anyAttribute namespace="##other" processContents="strict"/>
+ </xsd:complexType>
+ </xsd:element>
+</xsd:schema>
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/schemas/xliff-core-2.0.xsd b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/schemas/xliff-core-2.0.xsd
new file mode 100644
index 0000000..963232f
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/schemas/xliff-core-2.0.xsd
@@ -0,0 +1,411 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ XLIFF Version 2.0
+ OASIS Standard
+ 05 August 2014
+ Copyright (c) OASIS Open 2014. All rights reserved.
+ Source: http://docs.oasis-open.org/xliff/xliff-core/v2.0/os/schemas/
+ -->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ elementFormDefault="qualified"
+ xmlns:xlf="urn:oasis:names:tc:xliff:document:2.0"
+ targetNamespace="urn:oasis:names:tc:xliff:document:2.0">
+
+ <!-- Import -->
+
+ <xs:import namespace="http://www.w3.org/XML/1998/namespace"
+ schemaLocation="informativeCopiesOf3rdPartySchemas/w3c/xml.xsd"/>
+
+ <!-- Element Group -->
+
+ <xs:group name="inline">
+ <xs:choice>
+ <xs:element ref="xlf:cp"/>
+ <xs:element ref="xlf:ph"/>
+ <xs:element ref="xlf:pc"/>
+ <xs:element ref="xlf:sc"/>
+ <xs:element ref="xlf:ec"/>
+ <xs:element ref="xlf:mrk"/>
+ <xs:element ref="xlf:sm"/>
+ <xs:element ref="xlf:em"/>
+ </xs:choice>
+ </xs:group>
+
+ <!-- Attribute Types -->
+
+ <xs:simpleType name="yesNo">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="yes"/>
+ <xs:enumeration value="no"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="yesNoFirstNo">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="yes"/>
+ <xs:enumeration value="firstNo"/>
+ <xs:enumeration value="no"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="dirValue">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="ltr"/>
+ <xs:enumeration value="rtl"/>
+ <xs:enumeration value="auto"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="appliesTo">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="source"/>
+ <xs:enumeration value="target"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="userDefinedValue">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[^\s:]+:[^\s:]+"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="attrType_type">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="fmt"/>
+ <xs:enumeration value="ui"/>
+ <xs:enumeration value="quote"/>
+ <xs:enumeration value="link"/>
+ <xs:enumeration value="image"/>
+ <xs:enumeration value="other"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="typeForMrkValues">
+ <xs:restriction base="xs:NMTOKEN">
+ <xs:enumeration value="generic"/>
+ <xs:enumeration value="comment"/>
+ <xs:enumeration value="term"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="attrType_typeForMrk">
+ <xs:union memberTypes="xlf:typeForMrkValues xlf:userDefinedValue"/>
+ </xs:simpleType>
+
+ <xs:simpleType name="priorityValue">
+ <xs:restriction base="xs:positiveInteger">
+ <xs:minInclusive value="1"/>
+ <xs:maxInclusive value="10"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="stateType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="initial"/>
+ <xs:enumeration value="translated"/>
+ <xs:enumeration value="reviewed"/>
+ <xs:enumeration value="final"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <!-- Structural Elements -->
+
+ <xs:element name="xliff">
+ <xs:complexType mixed="false">
+ <xs:sequence>
+ <xs:element minOccurs="1" maxOccurs="unbounded" ref="xlf:file"/>
+ </xs:sequence>
+ <xs:attribute name="version" use="required"/>
+ <xs:attribute name="srcLang" use="required"/>
+ <xs:attribute name="trgLang" use="optional"/>
+ <xs:attribute ref="xml:space" use="optional" default="default"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="file">
+ <xs:complexType mixed="false">
+ <xs:sequence>
+ <xs:element minOccurs="0" maxOccurs="1" ref="xlf:skeleton"/>
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"
+ processContents="lax"/>
+ <xs:element minOccurs="0" maxOccurs="1" ref="xlf:notes"/>
+ <xs:choice minOccurs="1" maxOccurs="unbounded">
+ <xs:element ref="xlf:unit"/>
+ <xs:element ref="xlf:group"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="canResegment" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="original" use="optional"/>
+ <xs:attribute name="translate" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="srcDir" use="optional" type="xlf:dirValue" default="auto"/>
+ <xs:attribute name="trgDir" use="optional" type="xlf:dirValue" default="auto"/>
+ <xs:attribute ref="xml:space" use="optional"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="skeleton">
+ <xs:complexType mixed="true">
+ <xs:sequence>
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"
+ processContents="lax"/>
+ </xs:sequence>
+ <xs:attribute name="href" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="group">
+ <xs:complexType mixed="false">
+ <xs:sequence>
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"
+ processContents="lax"/>
+ <xs:element minOccurs="0" maxOccurs="1" ref="xlf:notes"/>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="xlf:unit"/>
+ <xs:element ref="xlf:group"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="name" use="optional"/>
+ <xs:attribute name="canResegment" use="optional" type="xlf:yesNo"/>
+ <xs:attribute name="translate" use="optional" type="xlf:yesNo"/>
+ <xs:attribute name="srcDir" use="optional" type="xlf:dirValue"/>
+ <xs:attribute name="trgDir" use="optional" type="xlf:dirValue"/>
+ <xs:attribute name="type" use="optional" type="xlf:userDefinedValue"/>
+ <xs:attribute ref="xml:space" use="optional"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="unit">
+ <xs:complexType mixed="false">
+ <xs:sequence>
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"
+ processContents="lax"/>
+ <xs:element minOccurs="0" maxOccurs="1" ref="xlf:notes"/>
+ <xs:element minOccurs="0" maxOccurs="1" ref="xlf:originalData"/>
+ <xs:choice minOccurs="1" maxOccurs="unbounded">
+ <xs:element ref="xlf:segment"/>
+ <xs:element ref="xlf:ignorable"/>
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="name" use="optional"/>
+ <xs:attribute name="canResegment" use="optional" type="xlf:yesNo"/>
+ <xs:attribute name="translate" use="optional" type="xlf:yesNo"/>
+ <xs:attribute name="srcDir" use="optional" type="xlf:dirValue"/>
+ <xs:attribute name="trgDir" use="optional" type="xlf:dirValue"/>
+ <xs:attribute ref="xml:space" use="optional"/>
+ <xs:attribute name="type" use="optional" type="xlf:userDefinedValue"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="segment">
+ <xs:complexType mixed="false">
+ <xs:sequence>
+ <xs:element minOccurs="1" maxOccurs="1" ref="xlf:source"/>
+ <xs:element minOccurs="0" maxOccurs="1" ref="xlf:target"/>
+ </xs:sequence>
+ <xs:attribute name="id" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="canResegment" use="optional" type="xlf:yesNo"/>
+ <xs:attribute name="state" use="optional" type="xlf:stateType" default="initial"/>
+ <xs:attribute name="subState" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="ignorable">
+ <xs:complexType mixed="false">
+ <xs:sequence>
+ <xs:element minOccurs="1" maxOccurs="1" ref="xlf:source"/>
+ <xs:element minOccurs="0" maxOccurs="1" ref="xlf:target"/>
+ </xs:sequence>
+ <xs:attribute name="id" use="optional" type="xs:NMTOKEN"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="notes">
+ <xs:complexType mixed="false">
+ <xs:sequence>
+ <xs:element minOccurs="1" maxOccurs="unbounded" ref="xlf:note"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="note">
+ <xs:complexType mixed="true">
+ <xs:attribute name="id" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="appliesTo" use="optional" type="xlf:appliesTo"/>
+ <xs:attribute name="category" use="optional"/>
+ <xs:attribute name="priority" use="optional" type="xlf:priorityValue" default="1"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="originalData">
+ <xs:complexType mixed="false">
+ <xs:sequence>
+ <xs:element minOccurs="1" maxOccurs="unbounded" ref="xlf:data"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="data">
+ <xs:complexType mixed="true">
+ <xs:sequence>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="xlf:cp"/>
+ </xs:sequence>
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="dir" use="optional" type="xlf:dirValue" default="auto"/>
+ <xs:attribute ref="xml:space" use="optional" fixed="preserve"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="source">
+ <xs:complexType mixed="true">
+ <xs:group ref="xlf:inline" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:attribute ref="xml:lang" use="optional"/>
+ <xs:attribute ref="xml:space" use="optional"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="target">
+ <xs:complexType mixed="true">
+ <xs:group ref="xlf:inline" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:attribute ref="xml:lang" use="optional"/>
+ <xs:attribute ref="xml:space" use="optional"/>
+ <xs:attribute name="order" use="optional" type="xs:positiveInteger"/>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- Inline Elements -->
+
+ <xs:element name="cp">
+ <!-- Code Point -->
+ <xs:complexType mixed="false">
+ <xs:attribute name="hex" use="required" type="xs:hexBinary"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="ph">
+ <!-- Placeholder -->
+ <xs:complexType mixed="false">
+ <xs:attribute name="canCopy" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canDelete" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canReorder" use="optional" type="xlf:yesNoFirstNo" default="yes"/>
+ <xs:attribute name="copyOf" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="disp" use="optional"/>
+ <xs:attribute name="equiv" use="optional"/>
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="dataRef" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="subFlows" use="optional" type="xs:NMTOKENS"/>
+ <xs:attribute name="subType" use="optional" type="xlf:userDefinedValue"/>
+ <xs:attribute name="type" use="optional" type="xlf:attrType_type"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="pc">
+ <!-- Paired Code -->
+ <xs:complexType mixed="true">
+ <xs:group ref="xlf:inline" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:attribute name="canCopy" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canDelete" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canOverlap" use="optional" type="xlf:yesNo"/>
+ <xs:attribute name="canReorder" use="optional" type="xlf:yesNoFirstNo" default="yes"/>
+ <xs:attribute name="copyOf" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="dispEnd" use="optional"/>
+ <xs:attribute name="dispStart" use="optional"/>
+ <xs:attribute name="equivEnd" use="optional"/>
+ <xs:attribute name="equivStart" use="optional"/>
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="dataRefEnd" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="dataRefStart" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="subFlowsEnd" use="optional" type="xs:NMTOKENS"/>
+ <xs:attribute name="subFlowsStart" use="optional" type="xs:NMTOKENS"/>
+ <xs:attribute name="subType" use="optional" type="xlf:userDefinedValue"/>
+ <xs:attribute name="type" use="optional" type="xlf:attrType_type"/>
+ <xs:attribute name="dir" use="optional" type="xlf:dirValue"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="sc">
+ <!-- Start Code -->
+ <xs:complexType mixed="false">
+ <xs:attribute name="canCopy" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canDelete" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canOverlap" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canReorder" use="optional" type="xlf:yesNoFirstNo" default="yes"/>
+ <xs:attribute name="copyOf" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="dataRef" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="dir" use="optional" type="xlf:dirValue"/>
+ <xs:attribute name="disp" use="optional"/>
+ <xs:attribute name="equiv" use="optional"/>
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="isolated" use="optional" type="xlf:yesNo" default="no"/>
+ <xs:attribute name="subFlows" use="optional" type="xs:NMTOKENS"/>
+ <xs:attribute name="subType" use="optional" type="xlf:userDefinedValue"/>
+ <xs:attribute name="type" use="optional" type="xlf:attrType_type"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="ec">
+ <!-- End Code -->
+ <xs:complexType mixed="false">
+ <xs:attribute name="canCopy" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canDelete" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canOverlap" use="optional" type="xlf:yesNo" default="yes"/>
+ <xs:attribute name="canReorder" use="optional" type="xlf:yesNoFirstNo" default="yes"/>
+ <xs:attribute name="copyOf" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="dataRef" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="dir" use="optional" type="xlf:dirValue"/>
+ <xs:attribute name="disp" use="optional"/>
+ <xs:attribute name="equiv" use="optional"/>
+ <xs:attribute name="id" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="isolated" use="optional" type="xlf:yesNo" default="no"/>
+ <xs:attribute name="startRef" use="optional" type="xs:NMTOKEN"/>
+ <xs:attribute name="subFlows" use="optional" type="xs:NMTOKENS"/>
+ <xs:attribute name="subType" use="optional" type="xlf:userDefinedValue"/>
+ <xs:attribute name="type" use="optional" type="xlf:attrType_type"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="mrk">
+ <!-- Annotation Marker -->
+ <xs:complexType mixed="true">
+ <xs:group ref="xlf:inline" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="translate" use="optional" type="xlf:yesNo"/>
+ <xs:attribute name="type" use="optional" type="xlf:attrType_typeForMrk"/>
+ <xs:attribute name="ref" use="optional" type="xs:anyURI"/>
+ <xs:attribute name="value" use="optional"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="sm">
+ <!-- Start Annotation Marker -->
+ <xs:complexType mixed="false">
+ <xs:attribute name="id" use="required" type="xs:NMTOKEN"/>
+ <xs:attribute name="translate" use="optional" type="xlf:yesNo"/>
+ <xs:attribute name="type" use="optional" type="xlf:attrType_typeForMrk"/>
+ <xs:attribute name="ref" use="optional" type="xs:anyURI"/>
+ <xs:attribute name="value" use="optional"/>
+ <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="em">
+ <!-- End Annotation Marker -->
+ <xs:complexType mixed="false">
+ <xs:attribute name="startRef" use="required" type="xs:NMTOKEN"/>
+ </xs:complexType>
+ </xs:element>
+
+</xs:schema>
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/schemas/xml.xsd b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/schemas/xml.xsd
new file mode 100644
index 0000000..a46162a
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Resources/schemas/xml.xsd
@@ -0,0 +1,309 @@
+<?xml version='1.0'?>
+<?xml-stylesheet href="../2008/09/xsd.xsl" type="text/xsl"?>
+<xs:schema targetNamespace="http://www.w3.org/XML/1998/namespace"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns ="http://www.w3.org/1999/xhtml"
+ xml:lang="en">
+
+ <xs:annotation>
+ <xs:documentation>
+ <div>
+ <h1>About the XML namespace</h1>
+
+ <div class="bodytext">
+ <p>
+
+ This schema document describes the XML namespace, in a form
+ suitable for import by other schema documents.
+ </p>
+ <p>
+ See <a href="http://www.w3.org/XML/1998/namespace.html">
+ http://www.w3.org/XML/1998/namespace.html</a> and
+ <a href="http://www.w3.org/TR/REC-xml">
+ http://www.w3.org/TR/REC-xml</a> for information
+ about this namespace.
+ </p>
+
+ <p>
+ Note that local names in this namespace are intended to be
+ defined only by the World Wide Web Consortium or its subgroups.
+ The names currently defined in this namespace are listed below.
+ They should not be used with conflicting semantics by any Working
+ Group, specification, or document instance.
+ </p>
+ <p>
+ See further below in this document for more information about <a
+ href="#usage">how to refer to this schema document from your own
+ XSD schema documents</a> and about <a href="#nsversioning">the
+ namespace-versioning policy governing this schema document</a>.
+ </p>
+ </div>
+ </div>
+
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:attribute name="lang">
+ <xs:annotation>
+ <xs:documentation>
+ <div>
+
+ <h3>lang (as an attribute name)</h3>
+ <p>
+
+ denotes an attribute whose value
+ is a language code for the natural language of the content of
+ any element; its value is inherited. This name is reserved
+ by virtue of its definition in the XML specification.</p>
+
+ </div>
+ <div>
+ <h4>Notes</h4>
+ <p>
+ Attempting to install the relevant ISO 2- and 3-letter
+ codes as the enumerated possible values is probably never
+ going to be a realistic possibility.
+ </p>
+ <p>
+
+ See BCP 47 at <a href="http://www.rfc-editor.org/rfc/bcp/bcp47.txt">
+ http://www.rfc-editor.org/rfc/bcp/bcp47.txt</a>
+ and the IANA language subtag registry at
+ <a href="http://www.iana.org/assignments/language-subtag-registry">
+ http://www.iana.org/assignments/language-subtag-registry</a>
+ for further information.
+ </p>
+ <p>
+
+ The union allows for the 'un-declaration' of xml:lang with
+ the empty string.
+ </p>
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:union memberTypes="xs:language">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value=""/>
+
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+ </xs:attribute>
+
+ <xs:attribute name="space">
+ <xs:annotation>
+ <xs:documentation>
+
+ <div>
+
+ <h3>space (as an attribute name)</h3>
+ <p>
+ denotes an attribute whose
+ value is a keyword indicating what whitespace processing
+ discipline is intended for the content of the element; its
+ value is inherited. This name is reserved by virtue of its
+ definition in the XML specification.</p>
+
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+
+ <xs:restriction base="xs:NCName">
+ <xs:enumeration value="default"/>
+ <xs:enumeration value="preserve"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+
+ <xs:attribute name="base" type="xs:anyURI"> <xs:annotation>
+ <xs:documentation>
+
+ <div>
+
+ <h3>base (as an attribute name)</h3>
+ <p>
+ denotes an attribute whose value
+ provides a URI to be used as the base for interpreting any
+ relative URIs in the scope of the element on which it
+ appears; its value is inherited. This name is reserved
+ by virtue of its definition in the XML Base specification.</p>
+
+ <p>
+ See <a
+ href="http://www.w3.org/TR/xmlbase/">http://www.w3.org/TR/xmlbase/</a>
+ for information about this attribute.
+ </p>
+
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+
+ <xs:attribute name="id" type="xs:ID">
+ <xs:annotation>
+ <xs:documentation>
+ <div>
+
+ <h3>id (as an attribute name)</h3>
+ <p>
+
+ denotes an attribute whose value
+ should be interpreted as if declared to be of type ID.
+ This name is reserved by virtue of its definition in the
+ xml:id specification.</p>
+
+ <p>
+ See <a
+ href="http://www.w3.org/TR/xml-id/">http://www.w3.org/TR/xml-id/</a>
+ for information about this attribute.
+ </p>
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+
+ </xs:attribute>
+
+ <xs:attributeGroup name="specialAttrs">
+ <xs:attribute ref="xml:base"/>
+ <xs:attribute ref="xml:lang"/>
+ <xs:attribute ref="xml:space"/>
+ <xs:attribute ref="xml:id"/>
+ </xs:attributeGroup>
+
+ <xs:annotation>
+
+ <xs:documentation>
+ <div>
+
+ <h3>Father (in any context at all)</h3>
+
+ <div class="bodytext">
+ <p>
+ denotes Jon Bosak, the chair of
+ the original XML Working Group. This name is reserved by
+ the following decision of the W3C XML Plenary and
+ XML Coordination groups:
+ </p>
+ <blockquote>
+ <p>
+
+ In appreciation for his vision, leadership and
+ dedication the W3C XML Plenary on this 10th day of
+ February, 2000, reserves for Jon Bosak in perpetuity
+ the XML name "xml:Father".
+ </p>
+ </blockquote>
+ </div>
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:annotation>
+ <xs:documentation>
+
+ <div xml:id="usage" id="usage">
+ <h2><a name="usage">About this schema document</a></h2>
+
+ <div class="bodytext">
+ <p>
+ This schema defines attributes and an attribute group suitable
+ for use by schemas wishing to allow <code>xml:base</code>,
+ <code>xml:lang</code>, <code>xml:space</code> or
+ <code>xml:id</code> attributes on elements they define.
+ </p>
+
+ <p>
+ To enable this, such a schema must import this schema for
+ the XML namespace, e.g. as follows:
+ </p>
+ <pre>
+ <schema.. .>
+ .. .
+ <import namespace="http://www.w3.org/XML/1998/namespace"
+ schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+ </pre>
+ <p>
+ or
+ </p>
+ <pre>
+
+ <import namespace="http://www.w3.org/XML/1998/namespace"
+ schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
+ </pre>
+ <p>
+ Subsequently, qualified reference to any of the attributes or the
+ group defined below will have the desired effect, e.g.
+ </p>
+ <pre>
+ <type.. .>
+ .. .
+ <attributeGroup ref="xml:specialAttrs"/>
+ </pre>
+ <p>
+ will define a type which will schema-validate an instance element
+ with any of those attributes.
+ </p>
+
+ </div>
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:annotation>
+ <xs:documentation>
+ <div id="nsversioning" xml:id="nsversioning">
+ <h2><a name="nsversioning">Versioning policy for this schema document</a></h2>
+
+ <div class="bodytext">
+ <p>
+ In keeping with the XML Schema WG's standard versioning
+ policy, this schema document will persist at
+ <a href="http://www.w3.org/2009/01/xml.xsd">
+ http://www.w3.org/2009/01/xml.xsd</a>.
+ </p>
+ <p>
+ At the date of issue it can also be found at
+ <a href="http://www.w3.org/2001/xml.xsd">
+ http://www.w3.org/2001/xml.xsd</a>.
+ </p>
+
+ <p>
+ The schema document at that URI may however change in the future,
+ in order to remain compatible with the latest version of XML
+ Schema itself, or with the XML namespace itself. In other words,
+ if the XML Schema or XML namespaces change, the version of this
+ document at <a href="http://www.w3.org/2001/xml.xsd">
+ http://www.w3.org/2001/xml.xsd
+ </a>
+ will change accordingly; the version at
+ <a href="http://www.w3.org/2009/01/xml.xsd">
+ http://www.w3.org/2009/01/xml.xsd
+ </a>
+ will not change.
+ </p>
+ <p>
+
+ Previous dated (and unchanging) versions of this schema
+ document are at:
+ </p>
+ <ul>
+ <li><a href="http://www.w3.org/2009/01/xml.xsd">
+ http://www.w3.org/2009/01/xml.xsd</a></li>
+ <li><a href="http://www.w3.org/2007/08/xml.xsd">
+ http://www.w3.org/2007/08/xml.xsd</a></li>
+ <li><a href="http://www.w3.org/2004/10/xml.xsd">
+
+ http://www.w3.org/2004/10/xml.xsd</a></li>
+ <li><a href="http://www.w3.org/2001/03/xml.xsd">
+ http://www.w3.org/2001/03/xml.xsd</a></li>
+ </ul>
+ </div>
+ </div>
+ </xs:documentation>
+ </xs:annotation>
+
+</xs:schema>
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Test/ProviderFactoryTestCase.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Test/ProviderFactoryTestCase.php
new file mode 100644
index 0000000..6d5f4b7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Test/ProviderFactoryTestCase.php
@@ -0,0 +1,147 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Test;
+
+use PHPUnit\Framework\TestCase;
+use Psr\Log\LoggerInterface;
+use Symfony\Component\HttpClient\MockHttpClient;
+use Symfony\Component\Translation\Dumper\XliffFileDumper;
+use Symfony\Component\Translation\Exception\IncompleteDsnException;
+use Symfony\Component\Translation\Exception\UnsupportedSchemeException;
+use Symfony\Component\Translation\Loader\LoaderInterface;
+use Symfony\Component\Translation\Provider\Dsn;
+use Symfony\Component\Translation\Provider\ProviderFactoryInterface;
+use Symfony\Contracts\HttpClient\HttpClientInterface;
+
+/**
+ * A test case to ease testing a translation provider factory.
+ *
+ * @author Mathieu Santostefano <msantostefano@protonmail.com>
+ *
+ * @internal
+ */
+abstract class ProviderFactoryTestCase extends TestCase
+{
+ protected $client;
+ protected $logger;
+ protected $defaultLocale;
+ protected $loader;
+ protected $xliffFileDumper;
+
+ abstract public function createFactory(): ProviderFactoryInterface;
+
+ /**
+ * @return iterable<array{0: bool, 1: string}>
+ */
+ abstract public function supportsProvider(): iterable;
+
+ /**
+ * @return iterable<array{0: string, 1: string, 2: TransportInterface}>
+ */
+ abstract public function createProvider(): iterable;
+
+ /**
+ * @return iterable<array{0: string, 1: string|null}>
+ */
+ public function unsupportedSchemeProvider(): iterable
+ {
+ return [];
+ }
+
+ /**
+ * @return iterable<array{0: string, 1: string|null}>
+ */
+ public function incompleteDsnProvider(): iterable
+ {
+ return [];
+ }
+
+ /**
+ * @dataProvider supportsProvider
+ */
+ public function testSupports(bool $expected, string $dsn)
+ {
+ $factory = $this->createFactory();
+
+ $this->assertSame($expected, $factory->supports(new Dsn($dsn)));
+ }
+
+ /**
+ * @dataProvider createProvider
+ */
+ public function testCreate(string $expected, string $dsn)
+ {
+ $factory = $this->createFactory();
+ $provider = $factory->create(new Dsn($dsn));
+
+ $this->assertSame($expected, (string) $provider);
+ }
+
+ /**
+ * @dataProvider unsupportedSchemeProvider
+ */
+ public function testUnsupportedSchemeException(string $dsn, string $message = null)
+ {
+ $factory = $this->createFactory();
+
+ $dsn = new Dsn($dsn);
+
+ $this->expectException(UnsupportedSchemeException::class);
+ if (null !== $message) {
+ $this->expectExceptionMessage($message);
+ }
+
+ $factory->create($dsn);
+ }
+
+ /**
+ * @dataProvider incompleteDsnProvider
+ */
+ public function testIncompleteDsnException(string $dsn, string $message = null)
+ {
+ $factory = $this->createFactory();
+
+ $dsn = new Dsn($dsn);
+
+ $this->expectException(IncompleteDsnException::class);
+ if (null !== $message) {
+ $this->expectExceptionMessage($message);
+ }
+
+ $factory->create($dsn);
+ }
+
+ protected function getClient(): HttpClientInterface
+ {
+ return $this->client ?? $this->client = new MockHttpClient();
+ }
+
+ protected function getLogger(): LoggerInterface
+ {
+ return $this->logger ?? $this->logger = $this->createMock(LoggerInterface::class);
+ }
+
+ protected function getDefaultLocale(): string
+ {
+ return $this->defaultLocale ?? $this->defaultLocale = 'en';
+ }
+
+ protected function getLoader(): LoaderInterface
+ {
+ return $this->loader ?? $this->loader = $this->createMock(LoaderInterface::class);
+ }
+
+ protected function getXliffFileDumper(): XliffFileDumper
+ {
+ return $this->xliffFileDumper ?? $this->xliffFileDumper = $this->createMock(XliffFileDumper::class);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Test/ProviderTestCase.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Test/ProviderTestCase.php
new file mode 100644
index 0000000..238fd96
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Test/ProviderTestCase.php
@@ -0,0 +1,86 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Test;
+
+use PHPUnit\Framework\MockObject\MockObject;
+use PHPUnit\Framework\TestCase;
+use Psr\Log\LoggerInterface;
+use Symfony\Component\HttpClient\MockHttpClient;
+use Symfony\Component\Translation\Dumper\XliffFileDumper;
+use Symfony\Component\Translation\Loader\LoaderInterface;
+use Symfony\Component\Translation\Provider\ProviderInterface;
+use Symfony\Contracts\HttpClient\HttpClientInterface;
+
+/**
+ * A test case to ease testing a translation provider.
+ *
+ * @author Mathieu Santostefano <msantostefano@protonmail.com>
+ *
+ * @internal
+ */
+abstract class ProviderTestCase extends TestCase
+{
+ protected $client;
+ protected $logger;
+ protected $defaultLocale;
+ protected $loader;
+ protected $xliffFileDumper;
+
+ abstract public function createProvider(HttpClientInterface $client, LoaderInterface $loader, LoggerInterface $logger, string $defaultLocale, string $endpoint): ProviderInterface;
+
+ /**
+ * @return iterable<array{0: string, 1: ProviderInterface}>
+ */
+ abstract public function toStringProvider(): iterable;
+
+ /**
+ * @dataProvider toStringProvider
+ */
+ public function testToString(ProviderInterface $provider, string $expected)
+ {
+ $this->assertSame($expected, (string) $provider);
+ }
+
+ protected function getClient(): MockHttpClient
+ {
+ return $this->client ?? $this->client = new MockHttpClient();
+ }
+
+ /**
+ * @return LoaderInterface&MockObject
+ */
+ protected function getLoader(): LoaderInterface
+ {
+ return $this->loader ?? $this->loader = $this->createMock(LoaderInterface::class);
+ }
+
+ /**
+ * @return LoaderInterface&MockObject
+ */
+ protected function getLogger(): LoggerInterface
+ {
+ return $this->logger ?? $this->logger = $this->createMock(LoggerInterface::class);
+ }
+
+ protected function getDefaultLocale(): string
+ {
+ return $this->defaultLocale ?? $this->defaultLocale = 'en';
+ }
+
+ /**
+ * @return LoaderInterface&MockObject
+ */
+ protected function getXliffFileDumper(): XliffFileDumper
+ {
+ return $this->xliffFileDumper ?? $this->xliffFileDumper = $this->createMock(XliffFileDumper::class);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/TranslatableMessage.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/TranslatableMessage.php
new file mode 100644
index 0000000..82ae6d7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/TranslatableMessage.php
@@ -0,0 +1,57 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+use Symfony\Contracts\Translation\TranslatableInterface;
+use Symfony\Contracts\Translation\TranslatorInterface;
+
+/**
+ * @author Nate Wiebe <nate@northern.co>
+ */
+class TranslatableMessage implements TranslatableInterface
+{
+ private $message;
+ private $parameters;
+ private $domain;
+
+ public function __construct(string $message, array $parameters = [], string $domain = null)
+ {
+ $this->message = $message;
+ $this->parameters = $parameters;
+ $this->domain = $domain;
+ }
+
+ public function __toString(): string
+ {
+ return $this->getMessage();
+ }
+
+ public function getMessage(): string
+ {
+ return $this->message;
+ }
+
+ public function getParameters(): array
+ {
+ return $this->parameters;
+ }
+
+ public function getDomain(): ?string
+ {
+ return $this->domain;
+ }
+
+ public function trans(TranslatorInterface $translator, string $locale = null): string
+ {
+ return $translator->trans($this->getMessage(), $this->getParameters(), $this->getDomain(), $locale);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Translator.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Translator.php
new file mode 100644
index 0000000..9a63956
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Translator.php
@@ -0,0 +1,490 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+use Symfony\Component\Config\ConfigCacheFactory;
+use Symfony\Component\Config\ConfigCacheFactoryInterface;
+use Symfony\Component\Config\ConfigCacheInterface;
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
+use Symfony\Component\Translation\Exception\RuntimeException;
+use Symfony\Component\Translation\Formatter\IntlFormatterInterface;
+use Symfony\Component\Translation\Formatter\MessageFormatter;
+use Symfony\Component\Translation\Formatter\MessageFormatterInterface;
+use Symfony\Component\Translation\Loader\LoaderInterface;
+use Symfony\Contracts\Translation\LocaleAwareInterface;
+use Symfony\Contracts\Translation\TranslatorInterface;
+
+// Help opcache.preload discover always-needed symbols
+class_exists(MessageCatalogue::class);
+
+/**
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class Translator implements TranslatorInterface, TranslatorBagInterface, LocaleAwareInterface
+{
+ /**
+ * @var MessageCatalogueInterface[]
+ */
+ protected $catalogues = [];
+
+ /**
+ * @var string
+ */
+ private $locale;
+
+ /**
+ * @var array
+ */
+ private $fallbackLocales = [];
+
+ /**
+ * @var LoaderInterface[]
+ */
+ private $loaders = [];
+
+ /**
+ * @var array
+ */
+ private $resources = [];
+
+ /**
+ * @var MessageFormatterInterface
+ */
+ private $formatter;
+
+ /**
+ * @var string
+ */
+ private $cacheDir;
+
+ /**
+ * @var bool
+ */
+ private $debug;
+
+ private $cacheVary;
+
+ /**
+ * @var ConfigCacheFactoryInterface|null
+ */
+ private $configCacheFactory;
+
+ /**
+ * @var array|null
+ */
+ private $parentLocales;
+
+ private $hasIntlFormatter;
+
+ /**
+ * @throws InvalidArgumentException If a locale contains invalid characters
+ */
+ public function __construct(string $locale, MessageFormatterInterface $formatter = null, string $cacheDir = null, bool $debug = false, array $cacheVary = [])
+ {
+ $this->setLocale($locale);
+
+ if (null === $formatter) {
+ $formatter = new MessageFormatter();
+ }
+
+ $this->formatter = $formatter;
+ $this->cacheDir = $cacheDir;
+ $this->debug = $debug;
+ $this->cacheVary = $cacheVary;
+ $this->hasIntlFormatter = $formatter instanceof IntlFormatterInterface;
+ }
+
+ public function setConfigCacheFactory(ConfigCacheFactoryInterface $configCacheFactory)
+ {
+ $this->configCacheFactory = $configCacheFactory;
+ }
+
+ /**
+ * Adds a Loader.
+ *
+ * @param string $format The name of the loader (@see addResource())
+ */
+ public function addLoader(string $format, LoaderInterface $loader)
+ {
+ $this->loaders[$format] = $loader;
+ }
+
+ /**
+ * Adds a Resource.
+ *
+ * @param string $format The name of the loader (@see addLoader())
+ * @param mixed $resource The resource name
+ *
+ * @throws InvalidArgumentException If the locale contains invalid characters
+ */
+ public function addResource(string $format, $resource, string $locale, string $domain = null)
+ {
+ if (null === $domain) {
+ $domain = 'messages';
+ }
+
+ $this->assertValidLocale($locale);
+ $locale ?: $locale = class_exists(\Locale::class) ? \Locale::getDefault() : 'en';
+
+ $this->resources[$locale][] = [$format, $resource, $domain];
+
+ if (\in_array($locale, $this->fallbackLocales)) {
+ $this->catalogues = [];
+ } else {
+ unset($this->catalogues[$locale]);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setLocale(string $locale)
+ {
+ $this->assertValidLocale($locale);
+ $this->locale = $locale;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getLocale()
+ {
+ return $this->locale ?: (class_exists(\Locale::class) ? \Locale::getDefault() : 'en');
+ }
+
+ /**
+ * Sets the fallback locales.
+ *
+ * @throws InvalidArgumentException If a locale contains invalid characters
+ */
+ public function setFallbackLocales(array $locales)
+ {
+ // needed as the fallback locales are linked to the already loaded catalogues
+ $this->catalogues = [];
+
+ foreach ($locales as $locale) {
+ $this->assertValidLocale($locale);
+ }
+
+ $this->fallbackLocales = $this->cacheVary['fallback_locales'] = $locales;
+ }
+
+ /**
+ * Gets the fallback locales.
+ *
+ * @internal
+ */
+ public function getFallbackLocales(): array
+ {
+ return $this->fallbackLocales;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function trans(?string $id, array $parameters = [], string $domain = null, string $locale = null)
+ {
+ if (null === $id || '' === $id) {
+ return '';
+ }
+
+ if (null === $domain) {
+ $domain = 'messages';
+ }
+
+ $catalogue = $this->getCatalogue($locale);
+ $locale = $catalogue->getLocale();
+ while (!$catalogue->defines($id, $domain)) {
+ if ($cat = $catalogue->getFallbackCatalogue()) {
+ $catalogue = $cat;
+ $locale = $catalogue->getLocale();
+ } else {
+ break;
+ }
+ }
+
+ $len = \strlen(MessageCatalogue::INTL_DOMAIN_SUFFIX);
+ if ($this->hasIntlFormatter
+ && ($catalogue->defines($id, $domain.MessageCatalogue::INTL_DOMAIN_SUFFIX)
+ || (\strlen($domain) > $len && 0 === substr_compare($domain, MessageCatalogue::INTL_DOMAIN_SUFFIX, -$len, $len)))
+ ) {
+ return $this->formatter->formatIntl($catalogue->get($id, $domain), $locale, $parameters);
+ }
+
+ return $this->formatter->format($catalogue->get($id, $domain), $locale, $parameters);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCatalogue(string $locale = null)
+ {
+ if (!$locale) {
+ $locale = $this->getLocale();
+ } else {
+ $this->assertValidLocale($locale);
+ }
+
+ if (!isset($this->catalogues[$locale])) {
+ $this->loadCatalogue($locale);
+ }
+
+ return $this->catalogues[$locale];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCatalogues(): array
+ {
+ return array_values($this->catalogues);
+ }
+
+ /**
+ * Gets the loaders.
+ *
+ * @return array LoaderInterface[]
+ */
+ protected function getLoaders()
+ {
+ return $this->loaders;
+ }
+
+ protected function loadCatalogue(string $locale)
+ {
+ if (null === $this->cacheDir) {
+ $this->initializeCatalogue($locale);
+ } else {
+ $this->initializeCacheCatalogue($locale);
+ }
+ }
+
+ protected function initializeCatalogue(string $locale)
+ {
+ $this->assertValidLocale($locale);
+
+ try {
+ $this->doLoadCatalogue($locale);
+ } catch (NotFoundResourceException $e) {
+ if (!$this->computeFallbackLocales($locale)) {
+ throw $e;
+ }
+ }
+ $this->loadFallbackCatalogues($locale);
+ }
+
+ private function initializeCacheCatalogue(string $locale): void
+ {
+ if (isset($this->catalogues[$locale])) {
+ /* Catalogue already initialized. */
+ return;
+ }
+
+ $this->assertValidLocale($locale);
+ $cache = $this->getConfigCacheFactory()->cache($this->getCatalogueCachePath($locale),
+ function (ConfigCacheInterface $cache) use ($locale) {
+ $this->dumpCatalogue($locale, $cache);
+ }
+ );
+
+ if (isset($this->catalogues[$locale])) {
+ /* Catalogue has been initialized as it was written out to cache. */
+ return;
+ }
+
+ /* Read catalogue from cache. */
+ $this->catalogues[$locale] = include $cache->getPath();
+ }
+
+ private function dumpCatalogue(string $locale, ConfigCacheInterface $cache): void
+ {
+ $this->initializeCatalogue($locale);
+ $fallbackContent = $this->getFallbackContent($this->catalogues[$locale]);
+
+ $content = sprintf(<<<EOF
+<?php
+
+use Symfony\Component\Translation\MessageCatalogue;
+
+\$catalogue = new MessageCatalogue('%s', %s);
+
+%s
+return \$catalogue;
+
+EOF
+ ,
+ $locale,
+ var_export($this->getAllMessages($this->catalogues[$locale]), true),
+ $fallbackContent
+ );
+
+ $cache->write($content, $this->catalogues[$locale]->getResources());
+ }
+
+ private function getFallbackContent(MessageCatalogue $catalogue): string
+ {
+ $fallbackContent = '';
+ $current = '';
+ $replacementPattern = '/[^a-z0-9_]/i';
+ $fallbackCatalogue = $catalogue->getFallbackCatalogue();
+ while ($fallbackCatalogue) {
+ $fallback = $fallbackCatalogue->getLocale();
+ $fallbackSuffix = ucfirst(preg_replace($replacementPattern, '_', $fallback));
+ $currentSuffix = ucfirst(preg_replace($replacementPattern, '_', $current));
+
+ $fallbackContent .= sprintf(<<<'EOF'
+$catalogue%s = new MessageCatalogue('%s', %s);
+$catalogue%s->addFallbackCatalogue($catalogue%s);
+
+EOF
+ ,
+ $fallbackSuffix,
+ $fallback,
+ var_export($this->getAllMessages($fallbackCatalogue), true),
+ $currentSuffix,
+ $fallbackSuffix
+ );
+ $current = $fallbackCatalogue->getLocale();
+ $fallbackCatalogue = $fallbackCatalogue->getFallbackCatalogue();
+ }
+
+ return $fallbackContent;
+ }
+
+ private function getCatalogueCachePath(string $locale): string
+ {
+ return $this->cacheDir.'/catalogue.'.$locale.'.'.strtr(substr(base64_encode(hash('sha256', serialize($this->cacheVary), true)), 0, 7), '/', '_').'.php';
+ }
+
+ /**
+ * @internal
+ */
+ protected function doLoadCatalogue(string $locale): void
+ {
+ $this->catalogues[$locale] = new MessageCatalogue($locale);
+
+ if (isset($this->resources[$locale])) {
+ foreach ($this->resources[$locale] as $resource) {
+ if (!isset($this->loaders[$resource[0]])) {
+ if (\is_string($resource[1])) {
+ throw new RuntimeException(sprintf('No loader is registered for the "%s" format when loading the "%s" resource.', $resource[0], $resource[1]));
+ }
+
+ throw new RuntimeException(sprintf('No loader is registered for the "%s" format.', $resource[0]));
+ }
+ $this->catalogues[$locale]->addCatalogue($this->loaders[$resource[0]]->load($resource[1], $locale, $resource[2]));
+ }
+ }
+ }
+
+ private function loadFallbackCatalogues(string $locale): void
+ {
+ $current = $this->catalogues[$locale];
+
+ foreach ($this->computeFallbackLocales($locale) as $fallback) {
+ if (!isset($this->catalogues[$fallback])) {
+ $this->initializeCatalogue($fallback);
+ }
+
+ $fallbackCatalogue = new MessageCatalogue($fallback, $this->getAllMessages($this->catalogues[$fallback]));
+ foreach ($this->catalogues[$fallback]->getResources() as $resource) {
+ $fallbackCatalogue->addResource($resource);
+ }
+ $current->addFallbackCatalogue($fallbackCatalogue);
+ $current = $fallbackCatalogue;
+ }
+ }
+
+ protected function computeFallbackLocales(string $locale)
+ {
+ if (null === $this->parentLocales) {
+ $this->parentLocales = json_decode(file_get_contents(__DIR__.'/Resources/data/parents.json'), true);
+ }
+
+ $locales = [];
+ foreach ($this->fallbackLocales as $fallback) {
+ if ($fallback === $locale) {
+ continue;
+ }
+
+ $locales[] = $fallback;
+ }
+
+ while ($locale) {
+ $parent = $this->parentLocales[$locale] ?? null;
+
+ if ($parent) {
+ $locale = 'root' !== $parent ? $parent : null;
+ } elseif (\function_exists('locale_parse')) {
+ $localeSubTags = locale_parse($locale);
+ $locale = null;
+ if (1 < \count($localeSubTags)) {
+ array_pop($localeSubTags);
+ $locale = locale_compose($localeSubTags) ?: null;
+ }
+ } elseif ($i = strrpos($locale, '_') ?: strrpos($locale, '-')) {
+ $locale = substr($locale, 0, $i);
+ } else {
+ $locale = null;
+ }
+
+ if (null !== $locale) {
+ array_unshift($locales, $locale);
+ }
+ }
+
+ return array_unique($locales);
+ }
+
+ /**
+ * Asserts that the locale is valid, throws an Exception if not.
+ *
+ * @throws InvalidArgumentException If the locale contains invalid characters
+ */
+ protected function assertValidLocale(string $locale)
+ {
+ if (!preg_match('/^[a-z0-9@_\\.\\-]*$/i', (string) $locale)) {
+ throw new InvalidArgumentException(sprintf('Invalid "%s" locale.', $locale));
+ }
+ }
+
+ /**
+ * Provides the ConfigCache factory implementation, falling back to a
+ * default implementation if necessary.
+ */
+ private function getConfigCacheFactory(): ConfigCacheFactoryInterface
+ {
+ if (!$this->configCacheFactory) {
+ $this->configCacheFactory = new ConfigCacheFactory($this->debug);
+ }
+
+ return $this->configCacheFactory;
+ }
+
+ private function getAllMessages(MessageCatalogueInterface $catalogue): array
+ {
+ $allMessages = [];
+
+ foreach ($catalogue->all() as $domain => $messages) {
+ if ($intlMessages = $catalogue->all($domain.MessageCatalogue::INTL_DOMAIN_SUFFIX)) {
+ $allMessages[$domain.MessageCatalogue::INTL_DOMAIN_SUFFIX] = $intlMessages;
+ $messages = array_diff_key($messages, $intlMessages);
+ }
+ if ($messages) {
+ $allMessages[$domain] = $messages;
+ }
+ }
+
+ return $allMessages;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/TranslatorBag.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/TranslatorBag.php
new file mode 100644
index 0000000..c655578
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/TranslatorBag.php
@@ -0,0 +1,105 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+use Symfony\Component\Translation\Catalogue\AbstractOperation;
+use Symfony\Component\Translation\Catalogue\TargetOperation;
+
+final class TranslatorBag implements TranslatorBagInterface
+{
+ /** @var MessageCatalogue[] */
+ private $catalogues = [];
+
+ public function addCatalogue(MessageCatalogue $catalogue): void
+ {
+ if (null !== $existingCatalogue = $this->getCatalogue($catalogue->getLocale())) {
+ $catalogue->addCatalogue($existingCatalogue);
+ }
+
+ $this->catalogues[$catalogue->getLocale()] = $catalogue;
+ }
+
+ public function addBag(TranslatorBagInterface $bag): void
+ {
+ foreach ($bag->getCatalogues() as $catalogue) {
+ $this->addCatalogue($catalogue);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCatalogue(string $locale = null)
+ {
+ if (null === $locale || !isset($this->catalogues[$locale])) {
+ $this->catalogues[$locale] = new MessageCatalogue($locale);
+ }
+
+ return $this->catalogues[$locale];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCatalogues(): array
+ {
+ return array_values($this->catalogues);
+ }
+
+ public function diff(TranslatorBagInterface $diffBag): self
+ {
+ $diff = new self();
+
+ foreach ($this->catalogues as $locale => $catalogue) {
+ if (null === $diffCatalogue = $diffBag->getCatalogue($locale)) {
+ $diff->addCatalogue($catalogue);
+
+ continue;
+ }
+
+ $operation = new TargetOperation($diffCatalogue, $catalogue);
+ $operation->moveMessagesToIntlDomainsIfPossible(AbstractOperation::NEW_BATCH);
+ $newCatalogue = new MessageCatalogue($locale);
+
+ foreach ($operation->getDomains() as $domain) {
+ $newCatalogue->add($operation->getNewMessages($domain), $domain);
+ }
+
+ $diff->addCatalogue($newCatalogue);
+ }
+
+ return $diff;
+ }
+
+ public function intersect(TranslatorBagInterface $intersectBag): self
+ {
+ $diff = new self();
+
+ foreach ($this->catalogues as $locale => $catalogue) {
+ if (null === $intersectCatalogue = $intersectBag->getCatalogue($locale)) {
+ continue;
+ }
+
+ $operation = new TargetOperation($catalogue, $intersectCatalogue);
+ $operation->moveMessagesToIntlDomainsIfPossible(AbstractOperation::OBSOLETE_BATCH);
+ $obsoleteCatalogue = new MessageCatalogue($locale);
+
+ foreach ($operation->getDomains() as $domain) {
+ $obsoleteCatalogue->add($operation->getObsoleteMessages($domain), $domain);
+ }
+
+ $diff->addCatalogue($obsoleteCatalogue);
+ }
+
+ return $diff;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/TranslatorBagInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/TranslatorBagInterface.php
new file mode 100644
index 0000000..4228977
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/TranslatorBagInterface.php
@@ -0,0 +1,35 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation;
+
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+
+/**
+ * TranslatorBagInterface.
+ *
+ * @method MessageCatalogueInterface[] getCatalogues() Returns all catalogues of the instance
+ *
+ * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
+ */
+interface TranslatorBagInterface
+{
+ /**
+ * Gets the catalogue by locale.
+ *
+ * @param string|null $locale The locale or null to use the default
+ *
+ * @return MessageCatalogueInterface
+ *
+ * @throws InvalidArgumentException If the locale contains invalid characters
+ */
+ public function getCatalogue(string $locale = null);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Util/ArrayConverter.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Util/ArrayConverter.php
new file mode 100644
index 0000000..acfbfc3
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Util/ArrayConverter.php
@@ -0,0 +1,99 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Util;
+
+/**
+ * ArrayConverter generates tree like structure from a message catalogue.
+ * e.g. this
+ * 'foo.bar1' => 'test1',
+ * 'foo.bar2' => 'test2'
+ * converts to follows:
+ * foo:
+ * bar1: test1
+ * bar2: test2.
+ *
+ * @author Gennady Telegin <gtelegin@gmail.com>
+ */
+class ArrayConverter
+{
+ /**
+ * Converts linear messages array to tree-like array.
+ * For example this array('foo.bar' => 'value') will be converted to ['foo' => ['bar' => 'value']].
+ *
+ * @param array $messages Linear messages array
+ *
+ * @return array Tree-like messages array
+ */
+ public static function expandToTree(array $messages)
+ {
+ $tree = [];
+
+ foreach ($messages as $id => $value) {
+ $referenceToElement = &self::getElementByPath($tree, explode('.', $id));
+
+ $referenceToElement = $value;
+
+ unset($referenceToElement);
+ }
+
+ return $tree;
+ }
+
+ private static function &getElementByPath(array &$tree, array $parts)
+ {
+ $elem = &$tree;
+ $parentOfElem = null;
+
+ foreach ($parts as $i => $part) {
+ if (isset($elem[$part]) && \is_string($elem[$part])) {
+ /* Process next case:
+ * 'foo': 'test1',
+ * 'foo.bar': 'test2'
+ *
+ * $tree['foo'] was string before we found array {bar: test2}.
+ * Treat new element as string too, e.g. add $tree['foo.bar'] = 'test2';
+ */
+ $elem = &$elem[implode('.', \array_slice($parts, $i))];
+ break;
+ }
+ $parentOfElem = &$elem;
+ $elem = &$elem[$part];
+ }
+
+ if ($elem && \is_array($elem) && $parentOfElem) {
+ /* Process next case:
+ * 'foo.bar': 'test1'
+ * 'foo': 'test2'
+ *
+ * $tree['foo'] was array = {bar: 'test1'} before we found string constant `foo`.
+ * Cancel treating $tree['foo'] as array and cancel back it expansion,
+ * e.g. make it $tree['foo.bar'] = 'test1' again.
+ */
+ self::cancelExpand($parentOfElem, $part, $elem);
+ }
+
+ return $elem;
+ }
+
+ private static function cancelExpand(array &$tree, string $prefix, array $node)
+ {
+ $prefix .= '.';
+
+ foreach ($node as $id => $value) {
+ if (\is_string($value)) {
+ $tree[$prefix.$id] = $value;
+ } else {
+ self::cancelExpand($tree, $prefix.$id, $value);
+ }
+ }
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Util/XliffUtils.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Util/XliffUtils.php
new file mode 100644
index 0000000..e4373a7
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Util/XliffUtils.php
@@ -0,0 +1,196 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Util;
+
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\Exception\InvalidResourceException;
+
+/**
+ * Provides some utility methods for XLIFF translation files, such as validating
+ * their contents according to the XSD schema.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class XliffUtils
+{
+ /**
+ * Gets xliff file version based on the root "version" attribute.
+ *
+ * Defaults to 1.2 for backwards compatibility.
+ *
+ * @throws InvalidArgumentException
+ */
+ public static function getVersionNumber(\DOMDocument $dom): string
+ {
+ /** @var \DOMNode $xliff */
+ foreach ($dom->getElementsByTagName('xliff') as $xliff) {
+ $version = $xliff->attributes->getNamedItem('version');
+ if ($version) {
+ return $version->nodeValue;
+ }
+
+ $namespace = $xliff->attributes->getNamedItem('xmlns');
+ if ($namespace) {
+ if (0 !== substr_compare('urn:oasis:names:tc:xliff:document:', $namespace->nodeValue, 0, 34)) {
+ throw new InvalidArgumentException(sprintf('Not a valid XLIFF namespace "%s".', $namespace));
+ }
+
+ return substr($namespace, 34);
+ }
+ }
+
+ // Falls back to v1.2
+ return '1.2';
+ }
+
+ /**
+ * Validates and parses the given file into a DOMDocument.
+ *
+ * @throws InvalidResourceException
+ */
+ public static function validateSchema(\DOMDocument $dom): array
+ {
+ $xliffVersion = static::getVersionNumber($dom);
+ $internalErrors = libxml_use_internal_errors(true);
+ if ($shouldEnable = self::shouldEnableEntityLoader()) {
+ $disableEntities = libxml_disable_entity_loader(false);
+ }
+ try {
+ $isValid = @$dom->schemaValidateSource(self::getSchema($xliffVersion));
+ if (!$isValid) {
+ return self::getXmlErrors($internalErrors);
+ }
+ } finally {
+ if ($shouldEnable) {
+ libxml_disable_entity_loader($disableEntities);
+ }
+ }
+
+ $dom->normalizeDocument();
+
+ libxml_clear_errors();
+ libxml_use_internal_errors($internalErrors);
+
+ return [];
+ }
+
+ private static function shouldEnableEntityLoader(): bool
+ {
+ // Version prior to 8.0 can be enabled without deprecation
+ if (\PHP_VERSION_ID < 80000) {
+ return true;
+ }
+
+ static $dom, $schema;
+ if (null === $dom) {
+ $dom = new \DOMDocument();
+ $dom->loadXML('<?xml version="1.0"?><test/>');
+
+ $tmpfile = tempnam(sys_get_temp_dir(), 'symfony');
+ register_shutdown_function(static function () use ($tmpfile) {
+ @unlink($tmpfile);
+ });
+ $schema = '<?xml version="1.0" encoding="utf-8"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <xsd:include schemaLocation="file:///'.str_replace('\\', '/', $tmpfile).'" />
+</xsd:schema>';
+ file_put_contents($tmpfile, '<?xml version="1.0" encoding="utf-8"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <xsd:element name="test" type="testType" />
+ <xsd:complexType name="testType"/>
+</xsd:schema>');
+ }
+
+ return !@$dom->schemaValidateSource($schema);
+ }
+
+ public static function getErrorsAsString(array $xmlErrors): string
+ {
+ $errorsAsString = '';
+
+ foreach ($xmlErrors as $error) {
+ $errorsAsString .= sprintf("[%s %s] %s (in %s - line %d, column %d)\n",
+ \LIBXML_ERR_WARNING === $error['level'] ? 'WARNING' : 'ERROR',
+ $error['code'],
+ $error['message'],
+ $error['file'],
+ $error['line'],
+ $error['column']
+ );
+ }
+
+ return $errorsAsString;
+ }
+
+ private static function getSchema(string $xliffVersion): string
+ {
+ if ('1.2' === $xliffVersion) {
+ $schemaSource = file_get_contents(__DIR__.'/../Resources/schemas/xliff-core-1.2-strict.xsd');
+ $xmlUri = 'http://www.w3.org/2001/xml.xsd';
+ } elseif ('2.0' === $xliffVersion) {
+ $schemaSource = file_get_contents(__DIR__.'/../Resources/schemas/xliff-core-2.0.xsd');
+ $xmlUri = 'informativeCopiesOf3rdPartySchemas/w3c/xml.xsd';
+ } else {
+ throw new InvalidArgumentException(sprintf('No support implemented for loading XLIFF version "%s".', $xliffVersion));
+ }
+
+ return self::fixXmlLocation($schemaSource, $xmlUri);
+ }
+
+ /**
+ * Internally changes the URI of a dependent xsd to be loaded locally.
+ */
+ private static function fixXmlLocation(string $schemaSource, string $xmlUri): string
+ {
+ $newPath = str_replace('\\', '/', __DIR__).'/../Resources/schemas/xml.xsd';
+ $parts = explode('/', $newPath);
+ $locationstart = 'file:///';
+ if (0 === stripos($newPath, 'phar://')) {
+ $tmpfile = tempnam(sys_get_temp_dir(), 'symfony');
+ if ($tmpfile) {
+ copy($newPath, $tmpfile);
+ $parts = explode('/', str_replace('\\', '/', $tmpfile));
+ } else {
+ array_shift($parts);
+ $locationstart = 'phar:///';
+ }
+ }
+
+ $drive = '\\' === \DIRECTORY_SEPARATOR ? array_shift($parts).'/' : '';
+ $newPath = $locationstart.$drive.implode('/', array_map('rawurlencode', $parts));
+
+ return str_replace($xmlUri, $newPath, $schemaSource);
+ }
+
+ /**
+ * Returns the XML errors of the internal XML parser.
+ */
+ private static function getXmlErrors(bool $internalErrors): array
+ {
+ $errors = [];
+ foreach (libxml_get_errors() as $error) {
+ $errors[] = [
+ 'level' => \LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR',
+ 'code' => $error->code,
+ 'message' => trim($error->message),
+ 'file' => $error->file ?: 'n/a',
+ 'line' => $error->line,
+ 'column' => $error->column,
+ ];
+ }
+
+ libxml_clear_errors();
+ libxml_use_internal_errors($internalErrors);
+
+ return $errors;
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Writer/TranslationWriter.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Writer/TranslationWriter.php
new file mode 100644
index 0000000..0a349b8
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Writer/TranslationWriter.php
@@ -0,0 +1,70 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Writer;
+
+use Symfony\Component\Translation\Dumper\DumperInterface;
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\Exception\RuntimeException;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * TranslationWriter writes translation messages.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+class TranslationWriter implements TranslationWriterInterface
+{
+ private $dumpers = [];
+
+ /**
+ * Adds a dumper to the writer.
+ */
+ public function addDumper(string $format, DumperInterface $dumper)
+ {
+ $this->dumpers[$format] = $dumper;
+ }
+
+ /**
+ * Obtains the list of supported formats.
+ *
+ * @return array
+ */
+ public function getFormats()
+ {
+ return array_keys($this->dumpers);
+ }
+
+ /**
+ * Writes translation from the catalogue according to the selected format.
+ *
+ * @param string $format The format to use to dump the messages
+ * @param array $options Options that are passed to the dumper
+ *
+ * @throws InvalidArgumentException
+ */
+ public function write(MessageCatalogue $catalogue, string $format, array $options = [])
+ {
+ if (!isset($this->dumpers[$format])) {
+ throw new InvalidArgumentException(sprintf('There is no dumper associated with format "%s".', $format));
+ }
+
+ // get the right dumper
+ $dumper = $this->dumpers[$format];
+
+ if (isset($options['path']) && !is_dir($options['path']) && !@mkdir($options['path'], 0777, true) && !is_dir($options['path'])) {
+ throw new RuntimeException(sprintf('Translation Writer was not able to create directory "%s".', $options['path']));
+ }
+
+ // save
+ $dumper->dump($catalogue, $options);
+ }
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Writer/TranslationWriterInterface.php b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Writer/TranslationWriterInterface.php
new file mode 100644
index 0000000..4321309
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/Writer/TranslationWriterInterface.php
@@ -0,0 +1,33 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Writer;
+
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\MessageCatalogue;
+
+/**
+ * TranslationWriter writes translation messages.
+ *
+ * @author Michel Salib <michelsalib@hotmail.com>
+ */
+interface TranslationWriterInterface
+{
+ /**
+ * Writes translation from the catalogue according to the selected format.
+ *
+ * @param string $format The format to use to dump the messages
+ * @param array $options Options that are passed to the dumper
+ *
+ * @throws InvalidArgumentException
+ */
+ public function write(MessageCatalogue $catalogue, string $format, array $options = []);
+}
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/composer.json b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/composer.json
new file mode 100644
index 0000000..de84e16
--- /dev/null
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/lib/vendor/symfony/translation/composer.json
@@ -0,0 +1,60 @@
+{
+ "name": "symfony/translation",
+ "type": "library",
+ "description": "Provides tools to internationalize your application",
+ "keywords": [],
+ "homepage": "https://symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=7.2.5",
+ "symfony/deprecation-contracts": "^2.1",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/polyfill-php80": "^1.16",
+ "symfony/translation-contracts": "^2.3"
+ },
+ "require-dev": {
+ "symfony/config": "^4.4|^5.0",
+ "symfony/console": "^4.4|^5.0",
+ "symfony/dependency-injection": "^5.0",
+ "symfony/http-kernel": "^5.0",
+ "symfony/intl": "^4.4|^5.0",
+ "symfony/polyfill-intl-icu": "^1.21",
+ "symfony/service-contracts": "^1.1.2|^2",
+ "symfony/yaml": "^4.4|^5.0",
+ "symfony/finder": "^4.4|^5.0",
+ "psr/log": "^1|^2|^3"
+ },
+ "conflict": {
+ "symfony/config": "<4.4",
+ "symfony/dependency-injection": "<5.0",
+ "symfony/http-kernel": "<5.0",
+ "symfony/twig-bundle": "<5.0",
+ "symfony/yaml": "<4.4"
+ },
+ "provide": {
+ "symfony/translation-implementation": "2.3"
+ },
+ "suggest": {
+ "symfony/config": "",
+ "symfony/yaml": "",
+ "psr/log-implementation": "To use logging capability in translator"
+ },
+ "autoload": {
+ "files": [ "Resources/functions.php" ],
+ "psr-4": { "Symfony\\Component\\Translation\\": "" },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "minimum-stability": "dev"
+}