Skip to content

Commit

Permalink
feat: add getTranslations and setTranslations on MoReader, remove use…
Browse files Browse the repository at this point in the history
…less code
  • Loading branch information
williamdes committed Mar 31, 2021
1 parent fcb7e79 commit b988af5
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 85 deletions.
2 changes: 1 addition & 1 deletion src/plugins/BasePlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ abstract class BasePlugin
*
* @param array $options The options for the plugin
*/
abstract public function __construct(array $options);
abstract public function __construct(array $options = []);

/**
* Get translation for a message id
Expand Down
123 changes: 69 additions & 54 deletions src/plugins/MoReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,29 +23,38 @@ class MoReader extends BasePlugin
public const ENDIAN_LITTLE = 2;

/**
* Data from mo file
* Translations
*
* @var stdClass
* @var array<string,string>
*/
private $data;
protected $translations = [];

/**
* File resource
* Build a MoReader instance
*
* @var resource
* @param array $options The options
*/
private $fileRes;
public function __construct(array $options = [])
{
$options = null;// Unused param detection
}

/**
* Build a MoReader instance
*
* @param array $options The options
* Set the translations
* @param array<string,string> $translations
*/
public function __construct(array $options)
public function setTranslations(array $translations): void
{
if (is_dir($options['localeDir']) == false) {
throw new Exception('The directory does not exist : ' . $options['localeDir']);
}
$this->translations = $translations;
}

/**
* Get the translations
* @return array<string,string> $translations
*/
public function getTranslations(): array
{
return $this->translations;
}

/**
Expand All @@ -56,84 +65,88 @@ public function __construct(array $options)
*/
public function readFile(string $file): stdClass
{
$this->data = new stdClass();
$data = new stdClass();
if (! is_file($file)) {
throw new Exception($file . ' does not exist.');
}
$res = fopen($file, 'rb');
if (is_resource($res)) {
$this->fileRes = $res;
$fileRes = $res;
} else {
throw new Exception($file . ' could not be open.');
}
$this->data->endian = self::determineByteOrder($this->fileRes);
if ($this->data->endian === -1) {
fclose($this->fileRes);
$data->endian = self::determineByteOrder($fileRes);
if ($data->endian === -1) {
fclose($fileRes);
throw new Exception($file . ' is not a valid gettext file.');
}

fseek($this->fileRes, 4);
$this->data->fileFormatRevision = self::readInteger($this->data->endian, $this->fileRes);
if ($this->data->fileFormatRevision !== 0 && $this->data->fileFormatRevision !== 1) {
fclose($this->fileRes);
fseek($fileRes, 4);
$data->fileFormatRevision = self::readInteger($data->endian, $fileRes);
if ($data->fileFormatRevision !== 0 && $data->fileFormatRevision !== 1) {
fclose($fileRes);
throw new Exception($file . ' has an unknown major revision.');
}
$this->data->nbrOfStrings = self::readInteger($this->data->endian, $this->fileRes);
$this->data->tableOffsetOriginal = self::readInteger($this->data->endian, $this->fileRes);//offset of table with original strings
$this->data->tableOffsetTranslation = self::readInteger($this->data->endian, $this->fileRes);//offset of table with translation strings
$data->nbrOfStrings = self::readInteger($data->endian, $fileRes);
$data->tableOffsetOriginal = self::readInteger($data->endian, $fileRes);//offset of table with original strings
$data->tableOffsetTranslation = self::readInteger($data->endian, $fileRes);//offset of table with translation strings

// see: https://gist.github.com/timwhitlock/8255619
// Hash table needs to be implemented if not useless
//$this->data->tblHashSize = self::readInteger($this->data->endian, $this->fileRes);//size of hashing table
//$this->data->hashTableOffsetStart = self::readInteger($this->data->endian, $this->fileRes);//offset of hashing table
//$this->data->hashTableOffsetEnd = $this->data->hashTableOffsetStart + $this->data->tblHashSize * 4;//offset of hashing table
//$data->tblHashSize = self::readInteger($data->endian, $fileRes);//size of hashing table
//$data->hashTableOffsetStart = self::readInteger($data->endian, $fileRes);//offset of hashing table
//$data->hashTableOffsetEnd = $data->hashTableOffsetStart + $data->tblHashSize * 4;//offset of hashing table

fseek($this->fileRes, $this->data->tableOffsetOriginal);
$this->data->msgIdTable = self::readIntegerList($this->data->endian, $this->fileRes, 2 * $this->data->nbrOfStrings);
fseek($this->fileRes, $this->data->tableOffsetTranslation);
$this->data->msgStrTable = self::readIntegerList($this->data->endian, $this->fileRes, 2 * $this->data->nbrOfStrings);
fseek($fileRes, $data->tableOffsetOriginal);
$data->msgIdTable = self::readIntegerList($data->endian, $fileRes, 2 * $data->nbrOfStrings);
fseek($fileRes, $data->tableOffsetTranslation);
$data->msgStrTable = self::readIntegerList($data->endian, $fileRes, 2 * $data->nbrOfStrings);

$this->data->translations = $this->readTranslations();
$this->translations = $this->readTranslations($fileRes, $data);
$data->translations = $this->translations;

// Clean memory
unset($this->data->tableOffsetOriginal);
unset($this->data->tableOffsetTranslation);
unset($this->data->fileFormatRevision);
unset($this->data->endian);
unset($this->data->msgIdTable);
unset($this->data->msgStrTable);
unset($data->tableOffsetOriginal);
unset($data->tableOffsetTranslation);
unset($data->fileFormatRevision);
unset($data->endian);
unset($data->msgIdTable);
unset($data->msgStrTable);

// Close resource
fclose($this->fileRes);
return $this->data;
fclose($fileRes);
return $data;
}

/**
* Read translations
*
* @copyright 2015 Max Grigorian
* @license MIT
* @return array
*
* @param resource $fileRes The mo file
* @param stdClass $data The data
* @return array<string,string>
*/
public function readTranslations(): array
public function readTranslations($fileRes, stdClass $data): array
{
$data = [];
for ($counter = 0; $counter < $this->data->nbrOfStrings; $counter++) {
$dataOut = [];
for ($counter = 0; $counter < $data->nbrOfStrings; $counter++) {
$msgId = null;
$msgStr = null;
try {
$msgId = $this->readStringFromTable($counter, $this->data->msgIdTable);
$msgId = $this->readStringFromTable($fileRes, $counter, $data->msgIdTable);
} catch (Exception $e) {
$msgId = [''];
}
try {
$msgStr = $this->readStringFromTable($counter, $this->data->msgStrTable);
$msgStr = $this->readStringFromTable($fileRes, $counter, $data->msgStrTable);
} catch (Exception $e) {
$msgStr = [];
}
$this->processRecord($data, $msgId, $msgStr);
$this->processRecord($dataOut, $msgId, $msgStr);
}
return $data;
return $dataOut;
}

/**
Expand All @@ -159,19 +172,21 @@ public function processRecord(array &$data, array $msgIds, array $msgStrs): void
*
* @copyright 2015 Max Grigorian
* @license MIT
*
* @param resource $fileRes The mo file
* @param int $index Position
* @param array $table Table
*
* @return array
*/
public function readStringFromTable(int $index, array $table): array
public function readStringFromTable($fileRes, int $index, array $table): array
{
$sizeKey = ($index * 2 ) + 1;
$size = $table[$sizeKey];
if ($size > 0) {
$offset = $table[$sizeKey + 1];
fseek($this->fileRes, $offset);
$read = fread($this->fileRes, $size);
fseek($fileRes, $offset);
$read = fread($fileRes, $size);
if (is_string($read)) {
return explode("\0", $read);
} else {
Expand Down Expand Up @@ -266,8 +281,8 @@ public static function readInteger(int $endian, $res)
*/
public function idOrFind(string $msgId): string
{
if (array_key_exists($msgId, $this->data->translations)) {
return $this->data->translations[$msgId];
if (array_key_exists($msgId, $this->translations)) {
return $this->translations[$msgId];
} else {
return $msgId;
}
Expand Down
49 changes: 44 additions & 5 deletions tests/I18nTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ class I18nTest extends TestCase
*/
private $twig = null;

/**
* The MoReader object
*
* @var MoReader
*/
private $moReader = null;

/**
* Set up the instance
*
Expand All @@ -45,11 +52,9 @@ public function setUp(): void
{
$dataDir = __DIR__ . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR;

$moReader = new MoReader(
['localeDir' => $dataDir]
);
$moReader->readFile($dataDir . 'abc.mo');
Launcher::setPlugin($moReader);
$this->moReader = new MoReader();
$this->moReader->readFile($dataDir . 'abc.mo');
Launcher::setPlugin($this->moReader);

$loader = new TwigLoaderFilesystem();
$this->memoryCache = new MemoryCache();
Expand All @@ -64,6 +69,40 @@ public function setUp(): void
$this->twig->addExtension(new ExtensionI18n());
}

/**
* Test simple translation using get and set
* @return void
*/
public function testSimpleTranslationGetSetTranslations(): void
{
$template = $this->twig->createTemplate(
'{% trans "Translate this" %}',
'testSimpleTranslationGetSetTranslations'
);
$html = $template->render([]);
$this->assertNotEmpty($html);
$this->assertEquals('Traduis ça', $html);
$this->moReader->setTranslations([]);
$this->assertSame($this->moReader->getTranslations(), []);
$html = $template->render([]);
$this->assertNotEmpty($html);
$this->assertEquals('Translate this', $html);
$this->moReader->setTranslations(
[
'Translate this' => 'blob blob blob',
]
);
$this->assertSame(
$this->moReader->getTranslations(),
[
'Translate this' => 'blob blob blob',
]
);
$html = $template->render([]);
$this->assertNotEmpty($html);
$this->assertEquals('blob blob blob', $html);
}

/**
* Test simple translation
* @return void
Expand Down
8 changes: 2 additions & 6 deletions tests/LauncherTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@ public function testGetText(): void
$S = DIRECTORY_SEPARATOR;
$dataDir = __DIR__ . $S . 'data' . $S;

$moReader = new MoReader(
['localeDir' => $dataDir]
);
$moReader = new MoReader();
$moReader->readFile($dataDir . 'abc.mo');
Launcher::setPlugin($moReader);
$this->assertSame('Traduis ça', Launcher::gettext('Translate this'));
Expand All @@ -48,9 +46,7 @@ public function testGetPlugin(): void
$S = DIRECTORY_SEPARATOR;
$dataDir = __DIR__ . $S . 'data' . $S;

$moReader = new MoReader(
['localeDir' => $dataDir]
);
$moReader = new MoReader();
$moReader->readFile($dataDir . 'abc.mo');
Launcher::setPlugin($moReader);
$this->assertSame($moReader, Launcher::getPlugin());
Expand Down
20 changes: 1 addition & 19 deletions tests/MoReaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,30 +31,12 @@ class MoReaderTest extends TestCase
*/
public function testInstance(): MoReader
{
$moReader = new MoReader(
['localeDir' => self::$dir]
);
$moReader = new MoReader();
$this->assertInstanceOf(MoReader::class, $moReader);

return $moReader;
}

/**
* test Dir does not exist
*
* @return void
*/
public function testException(): void
{
$folderString = self::$dir . str_shuffle('abcdefghijklmnopqrstuv');
$this->expectException(Exception::class);
$this->expectExceptionMessage('The directory does not exist : ' . $folderString);
$this->expectExceptionCode(0);
new MoReader(
['localeDir' => $folderString]
);
}

/**
* test read file
* @depends testInstance
Expand Down

0 comments on commit b988af5

Please sign in to comment.