Skip to content

Commit

Permalink
Merge 415cff3 into 8449d07
Browse files Browse the repository at this point in the history
  • Loading branch information
abbadon1334 committed Jul 15, 2019
2 parents 8449d07 + 415cff3 commit 4c11aa8
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 1 deletion.
11 changes: 11 additions & 0 deletions src/I18Next/Exception/TranslationSyntaxError.php
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace I18Next\Exception;

use atk4\core\Exception;

class TranslationSyntaxError extends Exception
{
}
71 changes: 71 additions & 0 deletions src/I18Next/Locale/Translations.php
Expand Up @@ -7,6 +7,7 @@
use atk4\core\ConfigTrait;
use atk4\core\Exception;
use DirectoryIterator;
use I18Next\Exception\TranslationSyntaxError;

/**
* @internal
Expand Down Expand Up @@ -54,6 +55,7 @@ public function load(string $path, bool $use_filename_as_namespace, ?string ...$
// normalizing
$this->afterReadProcessForKeyCounters();
$this->afterReadProcessForKeyDeepInline();

$this->afterReadAddNamespaceIfNeeded($configs, $fileInfo->getBasename('.'.$this->loader_format_ext));

// always reset config after every load
Expand Down Expand Up @@ -105,6 +107,10 @@ private function afterReadProcessForKeyCounters(): void
if ('plural' === $key_plural_definition || is_numeric($key_plural_definition)) {
$this->processForCounterKey($key_plural_definition, $key, $value);
}

if ('interval' === $key_plural_definition) {
$this->processForIntervalKey($key_plural_definition, $key, $value);
}
}
}

Expand Down Expand Up @@ -132,6 +138,71 @@ private function processForCounterKey(string $key_plural_definition, string $key
$this->setConfig($cleared_key.'/'.(string) $counter, $value);
}

private function processForIntervalKey(string $key_plural_definition, string $key, string $value): void
{
$cleared_key = substr(
$key,
0,
(strlen($key_plural_definition) + 1 /* the extra undescore before the plural_definition */) * -1
);

$check_last = substr($value, -1) === ';';

if (! $check_last) {
throw new TranslationSyntaxError([
'Interval declaration must end with ";" ('.$key.' => '.$value.')',
'key' => $key,
'value' => $value,
]);
}

$count_intervals = count(explode(';', trim($value, ';')));

$re = '/\((\S*)\)\{(.[^\}]*)\}/m';
//$str = '(1){one item};(2-7){a few items};(7-inf){a lot of items};';

preg_match_all($re, $value, $matches, PREG_SET_ORDER, 0);

if (count($matches) !== $count_intervals) {
throw new TranslationSyntaxError([
'Interval declaration syntax error ('.$key.' => '.$value.')',
'key' => $key,
'value' => $value,
]);
}

foreach ($matches as $match) {
if (count($match) < 3) {
throw new TranslationSyntaxError([
'Interval value syntax incorrect : '.$value,
'key' => $key,
'value' => $value,
'matches' => $matches,
'error_match' => $match,
]);
}

$interval = explode('-', $match[1]);

$interval_start = $interval[0];
$interval_end = $interval[1] ?? $interval[0];
if ($interval_end === 'inf') {
$interval_end = $interval_start;
}

$translation = $match[2];

if ($interval_start === $interval_end) {
$this->setConfig($cleared_key.'/'.(string) $interval_start, $translation);
continue;
}

for ($i = $interval_start; $i < $interval_end; $i++) {
$this->setConfig($cleared_key.'/'.(string) $i, $translation);
}
}
}

private function afterReadProcessForKeyDeepInline(): void
{
$filtered = array_filter($this->config, function ($key) {
Expand Down
89 changes: 89 additions & 0 deletions tests/Translator_CasePluralInterval_Test.php
@@ -0,0 +1,89 @@
<?php

namespace I18Next\Tests;

use I18Next\Exception\TranslationSyntaxError;
use I18Next\Translator;

class Translator_CasePluralInterval_Test extends TranslatorBaseCase
{
/**
* Testing this :
* "key4_interval": "(1){one item};(2-7){a few items};(7-inf){a lot of items};".
*
* "key4_interval": "(1){one item};(2-7){a few items};(7-inf){a lot of items};"
*/
public function testNoCount()
{
$this->setupTranslatorLanguages('en');

$result = $this->translator->_('key4');
$this->assertEquals('one item', $result);
}

public function testCount0()
{
$this->setupTranslatorLanguages('en');

$result = $this->translator->_('key4', ['count' => 0]);
$this->assertEquals('key4', $result);
}

public function testCount1()
{
$this->setupTranslatorLanguages('en');

$result = $this->translator->_('key4', ['count' => 1]);
$this->assertEquals('one item', $result);
}

public function testCount3()
{
$this->setupTranslatorLanguages('en');

$result = $this->translator->_('key4', ['count' => 3]);
$this->assertEquals('a few items', $result);
}

public function testCount8()
{
$this->setupTranslatorLanguages('en');

$result = $this->translator->_('key4', ['count' => 8]);
$this->assertEquals('a lot of items', $result);
}

public function testException1()
{
$this->expectException(TranslationSyntaxError::class);

$path = '/tmp/locale_exception';
@mkdir($path.'/en', 0777, true);

file_put_contents(
$path.'/en/exception.json',
json_encode(['key4_interval' => '(1){one item};2-7){a few items};(7-inf){a lot of items};'])
);

$this->translator = new Translator();
$this->translator->setTranslationsPath($path);
$this->translator->setLanguagePrimary('en');
}

public function testException2()
{
$this->expectException(TranslationSyntaxError::class);

$path = '/tmp/locale_exception';
@mkdir($path.'/en', 0777, true);

file_put_contents(
$path.'/en/exception.json',
json_encode(['key4_interval' => '(1){one item};(2-7){a few items};(7-inf){a lot of items}'])
);

$this->translator = new Translator();
$this->translator->setTranslationsPath($path);
$this->translator->setLanguagePrimary('en');
}
}
3 changes: 2 additions & 1 deletion tests/data/locales/en/key.json
Expand Up @@ -23,5 +23,6 @@
"key_4": "many",
"key_5": "other",
"key_nesting_interpolate1": "hello world",
"key_nesting_interpolate2": "say {{val}}"
"key_nesting_interpolate2": "say {{val}}",
"key4_interval": "(1){one item};(2-7){a few items};(7-inf){a lot of items};"
}
3 changes: 3 additions & 0 deletions tests/data/utils/cases.php
Expand Up @@ -131,6 +131,9 @@
'en' => 'user : {{user.first_name}} {{user.last_name}} with email : {{address.email}}',
'it' => 'utente : {{user.first_name}} {{user.last_name}} con email : {{address.email}}',
],
'key4_interval' => [
'en' => '(1){one item};(2-7){a few items};(7-inf){a lot of items};',
],
];

$path_def = [];
Expand Down

0 comments on commit 4c11aa8

Please sign in to comment.