mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
743 lines
27 KiB
PHP
743 lines
27 KiB
PHP
<?php
|
|
|
|
namespace SilverStripe\i18n\Tests;
|
|
|
|
use SilverStripe\Assets\Filesystem;
|
|
use SilverStripe\Control\Director;
|
|
use SilverStripe\Core\Convert;
|
|
use SilverStripe\Core\Manifest\ClassManifest;
|
|
use SilverStripe\Core\Manifest\ClassLoader;
|
|
use SilverStripe\Dev\SapphireTest;
|
|
use SilverStripe\i18n\i18n;
|
|
use SilverStripe\i18n\i18nRailsYamlAdapter;
|
|
use SilverStripe\i18n\Tests\i18nTest\CustomTranslatorAdapter;
|
|
use SilverStripe\i18n\Tests\i18nTest\MyObject;
|
|
use SilverStripe\i18n\Tests\i18nTest\MySubObject;
|
|
use SilverStripe\i18n\Tests\i18nTest\OtherCustomTranslatorAdapter;
|
|
use SilverStripe\i18n\Tests\i18nTest\TestDataObject;
|
|
use SilverStripe\i18n\Tests\i18nTest\TestObject;
|
|
use SilverStripe\View\ArrayData;
|
|
use SilverStripe\View\SSViewer;
|
|
use SilverStripe\View\ThemeResourceLoader;
|
|
use SilverStripe\View\ThemeManifest;
|
|
use Zend_Translate;
|
|
|
|
require_once 'Zend/Translate.php';
|
|
|
|
class i18nTest extends SapphireTest
|
|
{
|
|
|
|
/**
|
|
* @var string $tmpBasePath Used to write language files.
|
|
* We don't want to store them inside framework (or in any web-accessible place)
|
|
* in case something goes wrong with the file parsing.
|
|
*/
|
|
protected $alternateBaseSavePath;
|
|
|
|
/**
|
|
* @var string $alternateBasePath Fake webroot with a single module
|
|
* /i18ntestmodule which contains some files with _t() calls.
|
|
*/
|
|
protected $alternateBasePath;
|
|
|
|
protected $extraDataObjects = [
|
|
TestDataObject::class
|
|
];
|
|
|
|
protected $preloadClasses = [
|
|
OtherCustomTranslatorAdapter::class,
|
|
CustomTranslatorAdapter::class,
|
|
TestObject::class,
|
|
MySubObject::class,
|
|
MyObject::class
|
|
];
|
|
|
|
|
|
public function setUp()
|
|
{
|
|
parent::setUp();
|
|
|
|
// Force loading of classes before manifests potentially break autoloading
|
|
foreach ($this->preloadClasses as $class) {
|
|
if (!class_exists($class)) {
|
|
throw new \LogicException("Could not load class $class");
|
|
}
|
|
}
|
|
|
|
$s = DIRECTORY_SEPARATOR;
|
|
$this->alternateBasePath = __DIR__ . $s . 'i18nTest' . $s . "_fakewebroot";
|
|
$this->alternateBaseSavePath = TEMP_FOLDER . $s . 'i18nTextCollectorTest_webroot';
|
|
Filesystem::makeFolder($this->alternateBaseSavePath);
|
|
Director::config()->update('alternate_base_folder', $this->alternateBasePath);
|
|
|
|
// Replace old template loader with new one with alternate base path
|
|
$this->_oldLoader = ThemeResourceLoader::instance();
|
|
ThemeResourceLoader::set_instance($loader = new ThemeResourceLoader($this->alternateBasePath));
|
|
$loader->addSet(
|
|
'$default',
|
|
new ThemeManifest(
|
|
$this->alternateBasePath,
|
|
project(),
|
|
false,
|
|
true
|
|
)
|
|
);
|
|
|
|
SSViewer::config()->update('theme', 'testtheme1');
|
|
|
|
$this->originalLocale = i18n::get_locale();
|
|
|
|
// Override default adapter to avoid cached translations between tests.
|
|
// Emulates behaviour in i18n::get_translators()
|
|
$this->origAdapter = i18n::get_translator('core');
|
|
$adapter = new Zend_Translate(
|
|
array(
|
|
'adapter' => i18nRailsYamlAdapter::class,
|
|
'locale' => i18n::config()->get('default_locale'),
|
|
'disableNotices' => true,
|
|
)
|
|
);
|
|
i18n::register_translator($adapter, 'core');
|
|
$adapter->removeCache();
|
|
i18n::include_by_locale('en');
|
|
}
|
|
|
|
/**
|
|
* Number of test manifests
|
|
*
|
|
* @var int
|
|
*/
|
|
protected $manifests = 0;
|
|
|
|
/**
|
|
* Safely push a new class manifest.
|
|
* These will be cleaned up on tearDown()
|
|
*
|
|
* @param ClassManifest $manifest
|
|
*/
|
|
protected function pushManifest(ClassManifest $manifest)
|
|
{
|
|
$this->manifests++;
|
|
ClassLoader::instance()->pushManifest($manifest);
|
|
}
|
|
|
|
public function tearDown()
|
|
{
|
|
ThemeResourceLoader::set_instance($this->_oldLoader);
|
|
i18n::set_locale($this->originalLocale);
|
|
i18n::register_translator($this->origAdapter, 'core');
|
|
|
|
while ($this->manifests > 0) {
|
|
ClassLoader::instance()->popManifest();
|
|
$this->manifests--;
|
|
}
|
|
|
|
parent::tearDown();
|
|
}
|
|
|
|
public function testGetExistingTranslations()
|
|
{
|
|
$translations = i18n::get_existing_translations();
|
|
$this->assertTrue(isset($translations['en_US']), 'Checking for en translation');
|
|
$this->assertEquals($translations['en_US'], 'English (United States)');
|
|
$this->assertTrue(isset($translations['de_DE']), 'Checking for de_DE translation');
|
|
}
|
|
|
|
public function testGetClosestTranslation()
|
|
{
|
|
|
|
// Validate necessary assumptions for this test
|
|
$translations = i18n::get_existing_translations();
|
|
$this->assertTrue(isset($translations['en_US']));
|
|
$this->assertTrue(isset($translations['en_GB']));
|
|
$this->assertTrue(isset($translations['es_ES']));
|
|
$this->assertTrue(isset($translations['es_AR']));
|
|
$this->assertFalse(isset($translations['en_ZZ']));
|
|
$this->assertFalse(isset($translations['es_ZZ']));
|
|
$this->assertFalse(isset($translations['zz_ZZ']));
|
|
|
|
// Test indeterminate locales
|
|
$this->assertEmpty(i18n::get_closest_translation('zz_ZZ'));
|
|
|
|
// Test english fallback
|
|
$this->assertEquals('en_US', i18n::get_closest_translation('en_US'));
|
|
$this->assertEquals('en_GB', i18n::get_closest_translation('en_GB'));
|
|
$this->assertEquals('en_US', i18n::get_closest_translation('en_ZZ'));
|
|
|
|
// Test spanish fallbacks
|
|
$this->assertEquals('es_AR', i18n::get_closest_translation('es_AR'));
|
|
$this->assertEquals('es_ES', i18n::get_closest_translation('es_ES'));
|
|
$this->assertEquals('es_ES', i18n::get_closest_translation('es_XX'));
|
|
}
|
|
|
|
public function testDataObjectFieldLabels()
|
|
{
|
|
$oldLocale = i18n::get_locale();
|
|
i18n::set_locale('de_DE');
|
|
$obj = new i18nTest\TestDataObject();
|
|
|
|
i18n::get_translator('core')->getAdapter()->addTranslation(
|
|
array(
|
|
'i18nTest_DataObject.MyProperty' => 'MyProperty'
|
|
),
|
|
'en_US'
|
|
);
|
|
i18n::get_translator('core')->getAdapter()->addTranslation(
|
|
array(
|
|
'i18nTest_DataObject.MyProperty' => 'Mein Attribut'
|
|
),
|
|
'de_DE'
|
|
);
|
|
|
|
$this->assertEquals(
|
|
$obj->fieldLabel('MyProperty'),
|
|
'Mein Attribut'
|
|
);
|
|
|
|
i18n::get_translator('core')->getAdapter()->addTranslation(
|
|
array(
|
|
'i18nTest_DataObject.MyUntranslatedProperty' => 'Mein Attribut'
|
|
),
|
|
'en_US'
|
|
);
|
|
$this->assertEquals(
|
|
$obj->fieldLabel('MyUntranslatedProperty'),
|
|
'My Untranslated Property'
|
|
);
|
|
|
|
i18n::set_locale($oldLocale);
|
|
}
|
|
|
|
public function testProvideI18nEntities()
|
|
{
|
|
$oldLocale = i18n::get_locale();
|
|
i18n::set_locale('en_US');
|
|
|
|
i18n::get_translator('core')->getAdapter()->addTranslation(
|
|
array(
|
|
'i18nTest_Object.MyProperty' => 'Untranslated'
|
|
),
|
|
'en_US'
|
|
);
|
|
i18n::get_translator('core')->getAdapter()->addTranslation(
|
|
array(
|
|
'i18nTest_Object.my_translatable_property' => 'Übersetzt'
|
|
),
|
|
'de_DE'
|
|
);
|
|
|
|
$this->assertEquals(
|
|
i18nTest\TestObject::$my_translatable_property,
|
|
'Untranslated'
|
|
);
|
|
$this->assertEquals(
|
|
i18nTest\TestObject::my_translatable_property(),
|
|
'Untranslated'
|
|
);
|
|
|
|
i18n::set_locale('en_US');
|
|
$this->assertEquals(
|
|
i18nTest\TestObject::my_translatable_property(),
|
|
'Untranslated',
|
|
'Getter returns original static value when called in default locale'
|
|
);
|
|
|
|
i18n::set_locale('de_DE');
|
|
$this->assertEquals(
|
|
i18nTest\TestObject::my_translatable_property(),
|
|
'Übersetzt',
|
|
'Getter returns translated value when called in another locale'
|
|
);
|
|
}
|
|
|
|
public function testTemplateTranslation()
|
|
{
|
|
$oldLocale = i18n::get_locale();
|
|
|
|
i18n::set_locale('en_US');
|
|
i18n::get_translator('core')->getAdapter()->addTranslation(
|
|
array(
|
|
'i18nTestModule.MAINTEMPLATE' => 'Main Template',
|
|
'i18nTestModule.ss.SPRINTFNONAMESPACE' => 'My replacement no namespace: %s',
|
|
'i18nTestModule.LAYOUTTEMPLATE' => 'Layout Template',
|
|
'i18nTestModule.ss.LAYOUTTEMPLATENONAMESPACE' => 'Layout Template no namespace',
|
|
'i18nTestModule.SPRINTFNAMESPACE' => 'My replacement: %s',
|
|
'i18nTestModule.WITHNAMESPACE' => 'Include Entity with Namespace',
|
|
'i18nTestModuleInclude.ss.NONAMESPACE' => 'Include Entity without Namespace',
|
|
'i18nTestModuleInclude.ss.SPRINTFINCLUDENAMESPACE' => 'My include replacement: %s',
|
|
'i18nTestModuleInclude.ss.SPRINTFINCLUDENONAMESPACE' => 'My include replacement no namespace: %s'
|
|
),
|
|
'en_US'
|
|
);
|
|
|
|
$viewer = new SSViewer('i18nTestModule');
|
|
$parsedHtml = Convert::nl2os($viewer->process(new ArrayData(array('TestProperty' => 'TestPropertyValue'))));
|
|
$this->assertContains(
|
|
Convert::nl2os("Layout Template\n"),
|
|
$parsedHtml
|
|
);
|
|
$this->assertContains(
|
|
Convert::nl2os("Layout Template no namespace\n"),
|
|
$parsedHtml
|
|
);
|
|
|
|
i18n::set_locale('de_DE');
|
|
i18n::get_translator('core')->getAdapter()->addTranslation(
|
|
array(
|
|
'i18nTestModule.MAINTEMPLATE' => 'TRANS Main Template',
|
|
'i18nTestModule.ss.SPRINTFNONAMESPACE' => 'TRANS My replacement no namespace: %s',
|
|
'i18nTestModule.LAYOUTTEMPLATE' => 'TRANS Layout Template',
|
|
'i18nTestModule.ss.LAYOUTTEMPLATENONAMESPACE' => 'TRANS Layout Template no namespace',
|
|
'i18nTestModule.SPRINTFNAMESPACE' => 'TRANS My replacement: %s',
|
|
'i18nTestModule.WITHNAMESPACE' => 'TRANS Include Entity with Namespace',
|
|
'i18nTestModuleInclude.ss.NONAMESPACE' => 'TRANS Include Entity without Namespace',
|
|
'i18nTestModuleInclude.ss.SPRINTFINCLUDENAMESPACE' => 'TRANS My include replacement: %s',
|
|
'i18nTestModuleInclude.ss.SPRINTFINCLUDENONAMESPACE' => 'TRANS My include replacement no namespace: %s'
|
|
),
|
|
'de_DE'
|
|
);
|
|
|
|
$viewer = new SSViewer('i18nTestModule');
|
|
$parsedHtml = Convert::nl2os($viewer->process(new ArrayData(array('TestProperty' => 'TestPropertyValue'))));
|
|
$this->assertContains(
|
|
Convert::nl2os("TRANS Main Template\n"),
|
|
$parsedHtml
|
|
);
|
|
$this->assertContains(
|
|
Convert::nl2os("TRANS Layout Template\n"),
|
|
$parsedHtml
|
|
);
|
|
$this->assertContains(
|
|
Convert::nl2os("TRANS Layout Template no namespace\n"),
|
|
$parsedHtml
|
|
);
|
|
$this->assertContains(
|
|
Convert::nl2os("TRANS My replacement: TestPropertyValue\n"),
|
|
$parsedHtml
|
|
);
|
|
$this->assertContains(
|
|
Convert::nl2os("TRANS Include Entity with Namespace\n"),
|
|
$parsedHtml
|
|
);
|
|
$this->assertContains(
|
|
Convert::nl2os("TRANS Include Entity without Namespace\n"),
|
|
$parsedHtml
|
|
);
|
|
$this->assertContains(
|
|
Convert::nl2os("TRANS My include replacement: TestPropertyValue\n"),
|
|
$parsedHtml
|
|
);
|
|
$this->assertContains(
|
|
Convert::nl2os("TRANS My include replacement no namespace: TestPropertyValue\n"),
|
|
$parsedHtml
|
|
);
|
|
|
|
i18n::set_locale($oldLocale);
|
|
}
|
|
|
|
public function testNewTMethodSignature()
|
|
{
|
|
global $lang;
|
|
$oldLocale = i18n::get_locale();
|
|
|
|
i18n::set_locale('en_US');
|
|
|
|
i18n::get_translator('core')->getAdapter()->addTranslation(
|
|
array(
|
|
'i18nTestModule.NEWMETHODSIG' => 'TRANS New _t method signature test',
|
|
'i18nTestModule.INJECTIONS' => 'TRANS Hello {name} {greeting}. But it is late, {goodbye}',
|
|
'i18nTestModule.INJECTIONSLEGACY' => 'TRANS Hello %s %s. But it is late, %s',
|
|
),
|
|
'en_US'
|
|
);
|
|
|
|
$entity = "i18nTestModule.INJECTIONS";
|
|
$default = "Hello {name} {greeting}. But it is late, {goodbye}";
|
|
|
|
$translated = i18n::_t('i18nTestModule.NEWMETHODSIG', "New _t method signature test");
|
|
$this->assertContains(
|
|
"TRANS New _t method signature test",
|
|
$translated
|
|
);
|
|
|
|
$translated = i18n::_t(
|
|
$entity.'_DOES_NOT_EXIST',
|
|
$default,
|
|
array("name"=>"Mark", "greeting"=>"welcome", "goodbye"=>"bye")
|
|
);
|
|
$this->assertContains(
|
|
"Hello Mark welcome. But it is late, bye",
|
|
$translated,
|
|
"Testing fallback to the translation default (but using the injection array)"
|
|
);
|
|
|
|
$translated = i18n::_t(
|
|
$entity,
|
|
$default,
|
|
array("name"=>"Paul", "greeting"=>"good you are here", "goodbye"=>"see you")
|
|
);
|
|
$this->assertContains(
|
|
"TRANS Hello Paul good you are here. But it is late, see you",
|
|
$translated,
|
|
"Testing entity, default string and injection array"
|
|
);
|
|
|
|
$translated = i18n::_t(
|
|
$entity,
|
|
$default,
|
|
"New context (this should be ignored)",
|
|
array("name"=>"Steffen", "greeting"=>"willkommen", "goodbye"=>"wiedersehen")
|
|
);
|
|
$this->assertContains(
|
|
"TRANS Hello Steffen willkommen. But it is late, wiedersehen",
|
|
$translated,
|
|
"Full test of translation, using default, context and injection array"
|
|
);
|
|
|
|
$translated = i18n::_t($entity, array("name"=>"Cat", "greeting"=>"meow", "goodbye"=>"meow"));
|
|
$this->assertContains(
|
|
"TRANS Hello Cat meow. But it is late, meow",
|
|
$translated,
|
|
"Testing a translation with just entity and injection array"
|
|
);
|
|
|
|
$translated = i18n::_t(
|
|
'i18nTestModule.INJECTIONSLEGACY', // has %s placeholders
|
|
array("name"=>"Cat", "greeting2"=>"meow", "goodbye"=>"meow")
|
|
);
|
|
$this->assertContains(
|
|
"TRANS Hello Cat meow. But it is late, meow",
|
|
$translated,
|
|
"Testing sprintf placeholders with named injections"
|
|
);
|
|
|
|
$translated = i18n::_t(
|
|
'i18nTestModule.INJECTIONSLEGACY', // has %s placeholders
|
|
array("Cat", "meow"/*, "meow" */) // remove third arg
|
|
);
|
|
$this->assertContains(
|
|
"TRANS Hello Cat meow. But it is late, ",
|
|
$translated,
|
|
"Testing sprintf placeholders with unnamed injections and too few args"
|
|
);
|
|
|
|
$translated = i18n::_t(
|
|
'i18nTestModule.INJECTIONS', // has {name} placeholders
|
|
array("Cat", "meow", "meow")
|
|
);
|
|
$this->assertContains(
|
|
"TRANS Hello Cat meow. But it is late, meow",
|
|
$translated,
|
|
"Testing named injection placeholders with unnamed injections"
|
|
);
|
|
|
|
i18n::set_locale($oldLocale);
|
|
}
|
|
|
|
/**
|
|
* See @i18nTestModule.ss for the template that is being used for this test
|
|
* */
|
|
public function testNewTemplateTranslation()
|
|
{
|
|
global $lang;
|
|
$oldLocale = i18n::get_locale();
|
|
|
|
i18n::set_locale('en_US');
|
|
i18n::get_translator('core')->getAdapter()->addTranslation(
|
|
array(
|
|
'i18nTestModule.NEWMETHODSIG' => 'TRANS New _t method signature test',
|
|
'i18nTestModule.INJECTIONS' => 'TRANS Hello {name} {greeting}. But it is late, {goodbye}'
|
|
),
|
|
'en_US'
|
|
);
|
|
|
|
$viewer = new SSViewer('i18nTestModule');
|
|
$parsedHtml = Convert::nl2os($viewer->process(new ArrayData(array('TestProperty' => 'TestPropertyValue'))));
|
|
$this->assertContains(
|
|
Convert::nl2os("Hello Mark welcome. But it is late, bye\n"),
|
|
$parsedHtml,
|
|
"Testing fallback to the translation default (but using the injection array)"
|
|
);
|
|
|
|
$this->assertContains(
|
|
Convert::nl2os("TRANS Hello Paul good you are here. But it is late, see you\n"),
|
|
$parsedHtml,
|
|
"Testing entity, default string and injection array"
|
|
);
|
|
|
|
$this->assertContains(
|
|
Convert::nl2os("TRANS Hello Cat meow. But it is late, meow\n"),
|
|
$parsedHtml,
|
|
"Testing a translation with just entity and injection array"
|
|
);
|
|
|
|
//test injected calls
|
|
$this->assertContains(
|
|
Convert::nl2os(
|
|
"TRANS Hello ".Director::absoluteBaseURL()." ".i18n::get_locale().". But it is late, global calls\n"
|
|
),
|
|
$parsedHtml,
|
|
"Testing a translation with just entity and injection array, but with global variables injected in"
|
|
);
|
|
|
|
i18n::set_locale($oldLocale);
|
|
}
|
|
|
|
public function testGetLocaleFromLang()
|
|
{
|
|
$this->assertEquals('en_US', i18n::get_locale_from_lang('en'));
|
|
$this->assertEquals('de_DE', i18n::get_locale_from_lang('de_DE'));
|
|
$this->assertEquals('xy_XY', i18n::get_locale_from_lang('xy'));
|
|
}
|
|
|
|
public function testValidateLocale()
|
|
{
|
|
$this->assertTrue(i18n::validate_locale('en_US'), 'Known locale in underscore format is valid');
|
|
$this->assertTrue(i18n::validate_locale('en-US'), 'Known locale in dash format is valid');
|
|
$this->assertFalse(i18n::validate_locale('en'), 'Short lang format is not valid');
|
|
$this->assertFalse(i18n::validate_locale('xx_XX'), 'Unknown locale in correct format is not valid');
|
|
$this->assertFalse(i18n::validate_locale(''), 'Empty string is not valid');
|
|
}
|
|
|
|
public function testTranslate()
|
|
{
|
|
$oldLocale = i18n::get_locale();
|
|
|
|
i18n::get_translator('core')->getAdapter()->addTranslation(
|
|
array(
|
|
'i18nTestModule.ENTITY' => 'Entity with "Double Quotes"',
|
|
),
|
|
'en_US'
|
|
);
|
|
i18n::get_translator('core')->getAdapter()->addTranslation(
|
|
array(
|
|
'i18nTestModule.ENTITY' => 'Entity with "Double Quotes" (de)',
|
|
'i18nTestModule.ADDITION' => 'Addition (de)',
|
|
),
|
|
'de'
|
|
);
|
|
i18n::get_translator('core')->getAdapter()->addTranslation(
|
|
array(
|
|
'i18nTestModule.ENTITY' => 'Entity with "Double Quotes" (de_AT)',
|
|
),
|
|
'de_AT'
|
|
);
|
|
|
|
|
|
$this->assertEquals(
|
|
i18n::_t('i18nTestModule.ENTITY'),
|
|
'Entity with "Double Quotes"',
|
|
'Returns translation in default language'
|
|
);
|
|
|
|
i18n::set_locale('de');
|
|
$this->assertEquals(
|
|
i18n::_t('i18nTestModule.ENTITY'),
|
|
'Entity with "Double Quotes" (de)',
|
|
'Returns translation according to current locale'
|
|
);
|
|
|
|
i18n::set_locale('de_AT');
|
|
$this->assertEquals(
|
|
i18n::_t('i18nTestModule.ENTITY'),
|
|
'Entity with "Double Quotes" (de_AT)',
|
|
'Returns specific regional translation if available'
|
|
);
|
|
$this->assertEquals(
|
|
i18n::_t('i18nTestModule.ADDITION'),
|
|
'Addition (de)',
|
|
'Returns fallback non-regional translation if regional is not available'
|
|
);
|
|
|
|
i18n::set_locale('fr');
|
|
$this->assertEquals(
|
|
i18n::_t('i18nTestModule.ENTITY'),
|
|
'',
|
|
'Returns empty translation without default string if locale is not found'
|
|
);
|
|
$this->assertEquals(
|
|
i18n::_t('i18nTestModule.ENTITY', 'default'),
|
|
'default',
|
|
'Returns default string if locale is not found'
|
|
);
|
|
|
|
i18n::set_locale($oldLocale);
|
|
}
|
|
|
|
public function testIncludeByLocale()
|
|
{
|
|
// Looping through modules, so we can test the translation autoloading
|
|
// Load non-exclusive to retain core class autoloading
|
|
$classManifest = new ClassManifest($this->alternateBasePath, true, true, false);
|
|
$this->pushManifest($classManifest);
|
|
|
|
$adapter = i18n::get_translator('core')->getAdapter();
|
|
$this->assertTrue($adapter->isAvailable('en'));
|
|
$this->assertFalse($adapter->isAvailable('de'));
|
|
$this->assertFalse(
|
|
$adapter->isTranslated('i18nTestModule.ENTITY', 'de'),
|
|
'Existing unloaded entity not available before call'
|
|
);
|
|
$this->assertFalse(
|
|
$adapter->isTranslated('i18nTestModule.ENTITY', 'af'),
|
|
'Non-existing unloaded entity not available before call'
|
|
);
|
|
|
|
// set _fakewebroot module priority
|
|
i18n::config()->update('module_priority', array('subfolder','i18ntestmodule'));
|
|
|
|
i18n::include_by_locale('de');
|
|
|
|
$this->assertTrue($adapter->isAvailable('en'));
|
|
$this->assertTrue($adapter->isAvailable('de'));
|
|
$this->assertTrue($adapter->isTranslated('i18nTestModule.ENTITY', null, 'de'), 'Includes module files');
|
|
$this->assertTrue($adapter->isTranslated('i18nTestTheme1.LAYOUTTEMPLATE', null, 'de'), 'Includes theme files');
|
|
$this->assertTrue($adapter->isTranslated('i18nTestModule.OTHERENTITY', null, 'de'), 'Includes submodule files');
|
|
|
|
// check module priority
|
|
$this->assertEquals(
|
|
$adapter->translate('i18nTestModule.PRIORITYNOTICE', 'de'),
|
|
'High Module Priority (de)'
|
|
);
|
|
}
|
|
|
|
public function testIncludeByLocaleWithoutFallbackLanguage()
|
|
{
|
|
$classManifest = new ClassManifest($this->alternateBasePath, true, true, false);
|
|
$this->pushManifest($classManifest);
|
|
|
|
$adapter = i18n::get_translator('core')->getAdapter();
|
|
$this->assertTrue($adapter->isAvailable('en'));
|
|
$this->assertFalse($adapter->isAvailable('mi')); // not defined at all
|
|
$this->assertFalse($adapter->isAvailable('mi_NZ')); // defined, but not loaded yet
|
|
$this->assertFalse(
|
|
$adapter->isTranslated('i18nTestModule.ENTITY', 'mi'),
|
|
'Existing unloaded entity not available before call'
|
|
);
|
|
$this->assertFalse(
|
|
$adapter->isTranslated('i18nTestModule.ENTITY', 'mi_NZ'),
|
|
'Non-existing unloaded entity not available before call'
|
|
);
|
|
|
|
i18n::include_by_locale('mi_NZ');
|
|
|
|
$this->assertFalse($adapter->isAvailable('mi'));
|
|
$this->assertTrue($adapter->isAvailable('mi_NZ'));
|
|
$this->assertTrue($adapter->isTranslated('i18nTestModule.ENTITY', null, 'mi_NZ'), 'Includes module files');
|
|
}
|
|
|
|
public function testRegisterTranslator()
|
|
{
|
|
$translator = new Zend_Translate(
|
|
array(
|
|
'adapter' => CustomTranslatorAdapter::class,
|
|
'disableNotices' => true,
|
|
)
|
|
);
|
|
|
|
i18n::register_translator($translator, 'custom', 10);
|
|
$translators = i18n::get_translators();
|
|
$this->assertArrayHasKey('custom', $translators[10]);
|
|
$this->assertInstanceOf('Zend_Translate', $translators[10]['custom']);
|
|
$this->assertInstanceOf(CustomTranslatorAdapter::class, $translators[10]['custom']->getAdapter());
|
|
|
|
i18n::unregister_translator('custom');
|
|
$translators = i18n::get_translators();
|
|
$this->assertArrayNotHasKey('custom', $translators[10]);
|
|
}
|
|
|
|
public function testMultipleTranslators()
|
|
{
|
|
// Looping through modules, so we can test the translation autoloading
|
|
// Load non-exclusive to retain core class autoloading
|
|
$classManifest = new ClassManifest($this->alternateBasePath, true, true, false);
|
|
$this->pushManifest($classManifest);
|
|
|
|
// Changed manifest, so we also need to unset all previously collected messages.
|
|
// The easiest way to do this it to register a new adapter.
|
|
$adapter = new Zend_Translate(
|
|
array(
|
|
'adapter' => i18nRailsYamlAdapter::class,
|
|
'locale' => i18n::config()->get('default_locale'),
|
|
'disableNotices' => true,
|
|
)
|
|
);
|
|
i18n::register_translator($adapter, 'core');
|
|
|
|
i18n::set_locale('en_US');
|
|
|
|
$this->assertEquals(
|
|
i18n::_t('i18nTestModule.ENTITY'),
|
|
'Entity with "Double Quotes"'
|
|
);
|
|
$this->assertEquals(
|
|
i18n::_t('AdapterEntity1', 'AdapterEntity1'),
|
|
'AdapterEntity1',
|
|
'Falls back to default string if not found'
|
|
);
|
|
|
|
// Add a new translator
|
|
$translator = new Zend_Translate(
|
|
array(
|
|
'adapter' => CustomTranslatorAdapter::class,
|
|
'disableNotices' => true,
|
|
)
|
|
);
|
|
i18n::register_translator($translator, 'custom', 11);
|
|
$this->assertEquals(
|
|
i18n::_t('i18nTestModule.ENTITY'),
|
|
'i18nTestModule.ENTITY CustomAdapter (en_US)',
|
|
'Existing entities overruled by adapter with higher priority'
|
|
);
|
|
$this->assertEquals(
|
|
i18n::_t('AdapterEntity1', 'AdapterEntity1'),
|
|
'AdapterEntity1 CustomAdapter (en_US)',
|
|
'New entities only defined in new adapter are detected'
|
|
);
|
|
|
|
// Add a second new translator to test priorities
|
|
$translator = new Zend_Translate(
|
|
array(
|
|
'adapter' => OtherCustomTranslatorAdapter::class,
|
|
'disableNotices' => true,
|
|
)
|
|
);
|
|
i18n::register_translator($translator, 'othercustom_lower_prio', 5);
|
|
$this->assertEquals(
|
|
i18n::_t('i18nTestModule.ENTITY'),
|
|
'i18nTestModule.ENTITY CustomAdapter (en_US)',
|
|
'Adapter with lower priority loses'
|
|
);
|
|
|
|
// Add a third new translator to test priorities
|
|
$translator = new Zend_Translate(
|
|
array(
|
|
'adapter' => OtherCustomTranslatorAdapter::class,
|
|
'disableNotices' => true,
|
|
)
|
|
);
|
|
|
|
i18n::register_translator($translator, 'othercustom_higher_prio', 15);
|
|
|
|
$this->assertEquals(
|
|
i18n::_t('i18nTestModule.ENTITY'),
|
|
'i18nTestModule.ENTITY OtherCustomAdapter (en_US)',
|
|
'Adapter with higher priority wins'
|
|
);
|
|
|
|
i18n::unregister_translator('custom');
|
|
i18n::unregister_translator('othercustom_lower_prio');
|
|
i18n::unregister_translator('othercustom_higher_prio');
|
|
}
|
|
|
|
public function testGetLanguageName()
|
|
{
|
|
i18n::config()->update(
|
|
'common_languages',
|
|
array('de_CGN' => array('name' => 'German (Cologne)', 'native' => 'Kölsch'))
|
|
);
|
|
$this->assertEquals('German (Cologne)', i18n::get_language_name('de_CGN'));
|
|
$this->assertEquals('Kölsch', i18n::get_language_name('de_CGN', true));
|
|
}
|
|
}
|