Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions src/Service/MessageCatalogueFilterer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

/*
* This file is part of the PHP Translation package.
*
* (c) PHP Translation team <tobias.nyholm@gmail.com>
*
* For the full importright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Translation\Common\Service;

use Symfony\Component\Translation\MessageCatalogue;

final class MessageCatalogueFilterer
{
public function filterByDomains(MessageCatalogue $messageCatalogue, array $whitelistedDomains, array $blacklistedDomains): MessageCatalogue
{
$filteredMessageCatalogue = new MessageCatalogue($messageCatalogue->getLocale());

$translations = $messageCatalogue->all();
foreach ($messageCatalogue->getDomains() as $domain) {
if (!empty($blacklistedDomains) && \in_array($domain, $blacklistedDomains, true)) {
continue;
}

if (!empty($whitelistedDomains) && !\in_array($domain, $whitelistedDomains, true)) {
continue;
}

$filteredMessageCatalogue->add($translations[$domain], $domain);
}

return $filteredMessageCatalogue;
}
}
36 changes: 36 additions & 0 deletions src/Service/StorageImporter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

/*
* This file is part of the PHP Translation package.
*
* (c) PHP Translation team <tobias.nyholm@gmail.com>
*
* For the full importright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Translation\Common\Service;

use Symfony\Component\Translation\MessageCatalogue;
use Translation\Common\Storage\StorageInterface;

final class StorageImporter
{
/**
* This method import all messages from the source storage to the
* destination storage for given locales.
*
* * The source storage is not updated.
* * Translations already present in destination storage are overwritten.
* * Translations present in destination storage only are not deleted.
*/
public function import(StorageInterface $sourceStorage, StorageInterface $destinationStorage, array $locales): void
{
foreach ($locales as $locale) {
$messageCatalogue = new MessageCatalogue($locale);

$sourceStorage->export($messageCatalogue, []);
$destinationStorage->import($messageCatalogue, []);
}
}
}
33 changes: 33 additions & 0 deletions src/Service/StorageMessageCatalogueExtractor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

/*
* This file is part of the PHP Translation package.
*
* (c) PHP Translation team <tobias.nyholm@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Translation\Common\Service;

use Symfony\Component\Translation\MessageCatalogue;
use Translation\Common\Storage\StorageInterface;

final class StorageMessageCatalogueExtractor
{
public function extract(StorageInterface $storage, array $locales): array
{
$catalogues = [];

foreach ($locales as $locale) {
$catalogue = new MessageCatalogue($locale);

$storage->export($catalogue, []);

$catalogues[] = $catalogue;
}

return $catalogues;
}
}
95 changes: 95 additions & 0 deletions src/Storage/ArrayStorage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?php

/*
* This file is part of the PHP Translation package.
*
* (c) PHP Translation team <tobias.nyholm@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Translation\Common\Storage;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\MessageCatalogueInterface;
use Translation\Common\Model\Message;
use Translation\Common\Model\MessageInterface;

/**
* An in-memory storage.
*/
final class ArrayStorage implements StorageInterface
{
/**
* @var MessageCatalogue[]
*/
private $catalogues;

/**
* {@inheritdoc}
*/
public function get(string $locale, string $domain, string $key): ?MessageInterface
{
$translation = $this->getCatalogue($locale)->get($key, $domain);

return new Message($key, $domain, $locale, $translation);
}

/**
* {@inheritdoc}
*/
public function create(MessageInterface $message): void
{
$catalogue = $this->getCatalogue($message->getLocale());
if (!$catalogue->defines($message->getKey(), $message->getDomain())) {
$catalogue->set($message->getKey(), $message->getTranslation(), $message->getDomain());
}
}

/**
* {@inheritdoc}
*/
public function update(MessageInterface $message): void
{
$catalogue = $this->getCatalogue($message->getLocale());
$catalogue->set($message->getKey(), $message->getTranslation(), $message->getDomain());
}

/**
* {@inheritdoc}
*/
public function delete(string $locale, string $domain, string $key): void
{
$catalogue = $this->getCatalogue($locale);
$messages = $catalogue->all($domain);
unset($messages[$key]);

$catalogue->replace($messages, $domain);
}

/**
* {@inheritdoc}
*/
public function export(MessageCatalogueInterface $catalogue, array $options = []): void
{
$catalogue->addCatalogue($this->getCatalogue($catalogue->getLocale()));
}

/**
* {@inheritdoc}
*/
public function import(MessageCatalogueInterface $catalogue, array $options = []): void
{
$this->getCatalogue($catalogue->getLocale())->addCatalogue($catalogue);
}

private function getCatalogue(string $locale): MessageCatalogue
{
if (empty($this->catalogues[$locale])) {
$this->catalogues[$locale] = new MessageCatalogue($locale);
}

return $this->catalogues[$locale];
}
}
9 changes: 8 additions & 1 deletion src/Storage/ChainStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
*/
class ChainStorage implements StorageInterface
{
const DIRECTION_DOWN = 'down';

private $storages = [];

/**
Expand Down Expand Up @@ -83,7 +85,12 @@ public function delete(string $locale, string $domain, string $key): void
*/
public function export(MessageCatalogueInterface $catalogue, array $options = []): void
{
foreach ($this->storages as $storage) {
$storages = $this->storages;
if (isset($options['direction']) && self::DIRECTION_DOWN === $options['direction']) {
$storages = array_reverse($storages);
}

foreach ($storages as $storage) {
$storage->export($catalogue, $options);
}
}
Expand Down
10 changes: 7 additions & 3 deletions src/Storage/StorageInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,20 @@ public function delete(string $locale, string $domain, string $key): void;
/**
* Get messages from the storage into the $catalogue.
*
* This action should be considered as a "force merge". Existing messages
* in the storage will be overwritten but no message will be removed.
*
* @var array a list of arbitrary options that could be used. The array SHOULD
* use a format of array<string, array<mixed $value>.
* Example: ['foo' => ['bar', 'baz]]
*/
public function export(MessageCatalogueInterface $catalogue, array $options = []): void;

/**
* Populate the storage with all the messages in $catalogue. This action
* should be considered as a "force merge". Existing messages in the storage
* will be overwritten but no message will be removed.
* Populate the storage with all the messages in $catalogue.
*
* This action should be considered as a "force merge". Existing messages
* in the storage will be overwritten but no message will be removed.
*
* @var array a list of arbitrary options that could be used. The array SHOULD
* use a format of array<string, array<mixed $value>.
Expand Down
61 changes: 61 additions & 0 deletions tests/Unit/Service/MessageCatalogueFiltererTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

/*
* This file is part of the PHP Translation package.
*
* (c) PHP Translation team <tobias.nyholm@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Translation\Common\Tests\Unit\Service;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Translation\MessageCatalogue;
use Translation\Common\Service\MessageCatalogueFilterer;

class MessageCatalogueFiltererTest extends TestCase
{
public function testFilterWithoutWhitelistNorBlacklist()
{
$messageCatalogue = new MessageCatalogue('en');
$messageCatalogue->set('foo', 'foo', 'domain_1');
$messageCatalogue->set('bar', 'bar', 'domain_2');

$service = new MessageCatalogueFilterer();
$filteredMessageCatalogue = $service->filterByDomains($messageCatalogue, [], []);

$this->assertEquals($messageCatalogue, $filteredMessageCatalogue);
}

public function testFilterWithWhitelistOnly()
{
$messageCatalogue = new MessageCatalogue('en');
$messageCatalogue->set('foo', 'foo', 'domain_1');
$messageCatalogue->set('bar', 'bar', 'domain_2');

$expectedMessageCatalogue = new MessageCatalogue('en');
$expectedMessageCatalogue->set('foo', 'foo', 'domain_1');

$service = new MessageCatalogueFilterer();
$filteredMessageCatalogue = $service->filterByDomains($messageCatalogue, ['domain_1'], []);

$this->assertEquals($expectedMessageCatalogue, $filteredMessageCatalogue);
}

public function testFilterWithBlacklistOnly()
{
$messageCatalogue = new MessageCatalogue('en');
$messageCatalogue->set('foo', 'foo', 'domain_1');
$messageCatalogue->set('bar', 'bar', 'domain_2');

$expectedMessageCatalogue = new MessageCatalogue('en');
$expectedMessageCatalogue->set('foo', 'foo', 'domain_1');

$service = new MessageCatalogueFilterer();
$filteredMessageCatalogue = $service->filterByDomains($messageCatalogue, [], ['domain_2']);

$this->assertEquals($expectedMessageCatalogue, $filteredMessageCatalogue);
}
}
44 changes: 44 additions & 0 deletions tests/Unit/Service/StorageImporterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

/*
* This file is part of the PHP Translation package.
*
* (c) PHP Translation team <tobias.nyholm@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Translation\Common\Tests\Unit\Service;

use PHPUnit\Framework\TestCase;
use Translation\Common\Model\Message;
use Translation\Common\Service\StorageImporter;
use Translation\Common\Storage\ArrayStorage;

class StorageImporterTest extends TestCase
{
public function testImport()
{
$sourceStorage = new ArrayStorage();
$sourceStorage->create(new Message('common', 'messages', 'en', 'Translation from source storage'));
$sourceStorage->create(new Message('foo', 'messages', 'en', 'Only in source storage'));
$sourceStorage->create(new Message('baz', 'domain_1', 'en', 'Baz in domain 1'));
$destinationStorage = new ArrayStorage();
$destinationStorage->create(new Message('common', 'messages', 'en', 'Translation from destination storage'));
$destinationStorage->create(new Message('bar', 'messages', 'en', 'Only in destination storage'));
$destinationStorage->create(new Message('baz', 'domain_2', 'en', 'Baz in domain 2'));

$initialSourceStorage = clone $sourceStorage;
$expectedDestinationStorage = clone $destinationStorage;
$expectedDestinationStorage->update(new Message('common', 'messages', 'en', 'Translation from source storage'));
$expectedDestinationStorage->create(new Message('foo', 'messages', 'en', 'Only in source storage'));
$expectedDestinationStorage->create(new Message('baz', 'domain_1', 'en', 'Baz in domain 1'));

$importer = new StorageImporter();
$importer->import($sourceStorage, $destinationStorage, ['en']);

$this->assertEquals($initialSourceStorage, $sourceStorage);
$this->assertEquals($expectedDestinationStorage, $destinationStorage);
}
}
Loading