The Gitlab instance will be restarted on Monday April 28th at 2AM. There will be a short interruption of service.

Skip to content
Snippets Groups Projects
Commit 75a2e7cf authored by Ere Maijala's avatar Ere Maijala Committed by Robert Lange
Browse files

Expand capabilities of TranslatableStringInterface

- Support non-translatable content
- Support nested objects
parent 34539512
No related merge requests found
......@@ -52,16 +52,23 @@ class TranslatableString implements TranslatableStringInterface
*/
protected $displayString;
/**
* Whether translation is allowed
*/
protected $translatable;
/**
* Constructor
*
* @param string $string Original string
* @param string $displayString Translatable display string
* @param bool $translatable Whether translation is allowed
*/
public function __construct($string, $displayString)
public function __construct($string, $displayString, $translatable = true)
{
$this->string = (string)$string;
$this->displayString = $displayString;
$this->translatable = $translatable;
}
/**
......@@ -84,4 +91,14 @@ class TranslatableString implements TranslatableStringInterface
{
return $this->displayString;
}
/**
* Checks if the string can be translated
*
* @return bool
*/
public function isTranslatable()
{
return $this->translatable;
}
}
......@@ -45,4 +45,11 @@ interface TranslatableStringInterface
* @return string
*/
public function getDisplayString();
/**
* Checks if the string can be translated
*
* @return bool
*/
public function isTranslatable();
}
......@@ -106,6 +106,9 @@ trait TranslatorAwareTrait
// Special case: deal with objects with a designated display value:
if ($str instanceof \VuFind\I18n\TranslatableStringInterface) {
if (!$str->isTranslatable()) {
return $str->getDisplayString();
}
// On this pass, don't use the $default, since we want to fail over
// to getDisplayString before giving up:
$translated = $this
......@@ -114,7 +117,17 @@ trait TranslatorAwareTrait
return $translated;
}
// Override $domain/$str using getDisplayString() before proceeding:
list($domain, $str) = $this->extractTextDomain($str->getDisplayString());
$str = $str->getDisplayString();
// Also the display string can be a TranslatableString. This makes it
// possible have multiple levels of translatable values while still
// providing a sane default string if translation is not found. Used at
// least with hierarchical facets where translation key can be the exact
// facet value (e.g. "0/Book/") or a displayable value (e.g. "Book").
if ($str instanceof \VuFind\I18n\TranslatableStringInterface) {
return $this->translate($str, $tokens, $default);
} else {
list($domain, $str) = $this->extractTextDomain($str);
}
}
// Default case: deal with ordinary strings (or string-castable objects):
......@@ -204,7 +217,9 @@ trait TranslatorAwareTrait
}
if ($target instanceof \VuFind\I18n\TranslatableStringInterface) {
$class = get_class($target);
$parts[1] = new $class($parts[1], $target->getDisplayString());
$parts[1] = new $class(
$parts[1], $target->getDisplayString(), $target->isTranslatable()
);
}
return $parts;
}
......
<?php
/**
* TranslatableString Test Class
*
* Note that most tests using TranslatableString are in
* VuFindTest\View\Helper\Root\TranslateTest
*
* PHP version 7
*
* Copyright (C) The National Library of Finland 2020.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* @category VuFind
* @package Tests
* @author Ere Maijala <ere.maijala@helsinki.fi>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development:testing:unit_tests Wiki
*/
namespace VuFindTest\I18n\Translator\Loader;
use VuFind\I18n\TranslatableString;
/**
* TranslatableString Test Class
*
* Note that most tests using TranslatableString are in
* VuFindTest\View\Helper\Root\TranslateTest
*
* @category VuFind
* @package Tests
* @author Ere Maijala <ere.maijala@helsinki.fi>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development:testing:unit_tests Wiki
*/
class TranslatableStringTest extends \VuFindTest\Unit\TestCase
{
/**
* Test standalone behavior.
*
* @return void
*/
public function testWithoutTranslate()
{
$s = new TranslatableString('foo', 'bar');
$this->assertEquals('foo', (string)$s);
$this->assertEquals('bar', $s->getDisplayString());
$this->assertTrue($s->isTranslatable());
$s = new TranslatableString('foo', new TranslatableString('bar', 'baz'));
$this->assertEquals('foo', (string)$s);
$this->assertEquals('bar', (string)$s->getDisplayString());
$this->assertEquals('baz', $s->getDisplayString()->getDisplayString());
$this->assertTrue($s->isTranslatable());
$s = new TranslatableString('foo', 'bar', false);
$this->assertFalse($s->isTranslatable());
}
}
......@@ -127,6 +127,25 @@ class TranslateTest extends \PHPUnit\Framework\TestCase
);
}
/**
* Test TranslatableString default values.
*
* @return void
*/
public function testTranslateTranslatableStringDefaultValues()
{
$translate = new Translate();
$translate->setTranslator(
$this->getMockTranslator(['default' => []])
);
$s = new TranslatableString('foo', 'bar');
$this->assertEquals('bar', $translate->__invoke($s));
$s = new TranslatableString('foo', new TranslatableString('bar', 'baz'));
$this->assertEquals('baz', $translate->__invoke($s));
}
/**
* Test translation of a TranslatableString object with a loaded translator
*
......@@ -136,7 +155,12 @@ class TranslateTest extends \PHPUnit\Framework\TestCase
{
$translate = new Translate();
$translate->setTranslator(
$this->getMockTranslator(['default' => ['foo' => '%%token%%']])
$this->getMockTranslator(
[
'default' => ['foo' => '%%token%%'],
'other' => ['foo' => 'Foo', 'bar' => 'Bar']
]
)
);
// Test a TranslatableString with a translation.
......@@ -165,6 +189,22 @@ class TranslateTest extends \PHPUnit\Framework\TestCase
$str3, ['%%token%%' => 'baz'], 'failure'
)
);
// Test a TranslatableString with another TranslatableString as a fallback.
$str4 = new TranslatableString(
'xyzzy', new TranslatableString('bar', 'baz')
);
$this->assertEquals('baz', $translate->__invoke($str4));
$str5 = new TranslatableString(
'xyzzy', new TranslatableString('foo', 'baz')
);
$this->assertEquals('%%token%%', $translate->__invoke($str5));
// Test a TranslatableString with translation forbidden
$str6 = new TranslatableString('foo', 'bar', false);
$this->assertEquals('bar', $translate->__invoke($str6));
$str7 = new TranslatableString('foo', '', false);
$this->assertEquals('', $translate->__invoke($str7));
}
/**
......@@ -194,6 +234,40 @@ class TranslateTest extends \PHPUnit\Framework\TestCase
// No string translatable
$str3 = new TranslatableString('d1::f2', 'd2::f1');
$this->assertEquals('failure', $translate->__invoke($str3, [], 'failure'));
// Secondary string a translatable TranslatableString
$str4 = new TranslatableString(
'd1::f2', new TranslatableString('d2::f2', 'd3::f3')
);
$this->assertEquals('str2', $translate->__invoke($str4));
// Secondary string a TranslatableString with no translation
$str5 = new TranslatableString(
'd1::f2', new TranslatableString('d2::f1', 'failure')
);
$this->assertEquals('failure', $translate->__invoke($str5));
// Secondary string a non-translatable TranslatableString
$str6 = new TranslatableString(
'd1::f2', new TranslatableString('d2::f2', 'failure', false)
);
$this->assertEquals('failure', $translate->__invoke($str6));
// Three levels of TranslatableString with the last one translatable
$str7 = new TranslatableString(
'd1::f2',
new TranslatableString(
'd3::f3', new TranslatableString('d2::f2', 'failure')
)
);
$this->assertEquals('str2', $translate->__invoke($str7));
// Three levels of TranslatableString with no translation
$str8 = new TranslatableString(
'd1::f2',
new TranslatableString(
'd3::f3', new TranslatableString('d3::f2', 'failure')
)
);
$this->assertEquals('failure', $translate->__invoke($str8));
}
/**
......@@ -223,6 +297,27 @@ class TranslateTest extends \PHPUnit\Framework\TestCase
);
}
/**
* Test nested translation with potential text domain conflict
*
* @return void
*/
public function testTranslateNestedTextDomainWithConflict()
{
$translations = [
'd1' => ['foo' => 'bar', 'failure' => 'success'],
'd2' => ['baz' => 'xyzzy', 'failure' => 'mediocrity'],
];
$translate = new Translate();
$translate->setTranslator(
$this->getMockTranslator($translations)
);
$str = new TranslatableString(
'd1::baz', new TranslatableString('d2::foo', 'failure')
);
$this->assertEquals('failure', $translate->__invoke($str));
}
/**
* Test locale retrieval without a loaded translator
*
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment