ILIAS  trunk Revision v13.0_alpha-62-g3b72d83f2e5
PluralTxtTest.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
26use PHPUnit\Framework\Attributes\PreserveGlobalState;
27use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
28
33#[RunTestsInSeparateProcesses]
34#[PreserveGlobalState(false)]
36{
37 private ?string $fixture_directory = null;
38
39 protected function setUp(): void
40 {
42
43 if (!defined('ILIAS_ABSOLUTE_PATH')) {
44 define('ILIAS_ABSOLUTE_PATH', realpath(__DIR__ . '/../../../../'));
45 }
46 if (!defined('ILIAS_LOG_ENABLED')) {
47 define('ILIAS_LOG_ENABLED', false);
48 }
50 }
51
52 protected function tearDown(): void
53 {
54 if (isset($this->fixture_directory) && is_dir($this->fixture_directory)) {
55 array_map('unlink', glob($this->fixture_directory . '/*') ?: []);
56 rmdir($this->fixture_directory);
57 }
58 if (isset($this->fixture_directory)) {
59 MigratedPoFixture::removeShippedDirectory('components/ILIAS/Language/tests/' . basename($this->fixture_directory));
60 }
61 if (defined('CLIENT_DATA_DIR') && is_dir(CLIENT_DATA_DIR)) {
63 }
64
66 }
67
69 private function contributeModule(string $module, TranslationCatalog $catalog, ?TranslationCatalog $overlay = null): LanguageFileDirectory
70 {
72 $this->fixture_directory ??= __DIR__ . '/tmp-plural-txt-fixtures-' . bin2hex(random_bytes(4));
73
74 $relative_path = 'components/ILIAS/Language/tests/' . basename($this->fixture_directory) . '/';
75 if ($overlay !== null) {
76 MigratedPoFixture::writePair(rtrim(CLIENT_DATA_DIR, '/') . '/lang/' . $module . '/de/' . $module . '_de', $overlay);
77 }
78 MigratedPoFixture::writeShippedPo($relative_path, $module, 'de', $catalog);
79
80 return MigratedPoFixture::directory($module, $relative_path);
81 }
82
83 private function registerDirectoryManager(LanguageFileDirectory ...$contributed): void
84 {
85 $this->setGlobalVariable(
86 LanguageFileDirectoryManager::class,
88 );
89 }
90
91 private function stubUsageLogDependencies(): void
92 {
93 $this->setGlobalVariable('ilClientIniFile', $this->createStub(ilIniFile::class));
94 $this->setGlobalVariable('ilDB', $this->createStub(ilDBInterface::class));
95 }
96
98 private function stubComponentLogger(): void
99 {
100 $factory = $this->createStub(ilLoggerFactory::class);
101 $factory->method('getComponentLogger')->willReturn($this->createStub(ilLogger::class));
102 $this->setGlobalVariable('ilLoggerFactory', $factory);
103 }
104
105 private function buildLanguage(string $lang_key = 'de'): ilLanguage
106 {
107 global $DIC;
108 if ($DIC->offsetExists(LanguageFileDirectoryManager::class)) {
109 MigratedPoFixture::build($DIC[LanguageFileDirectoryManager::class], (string) ILIAS_ABSOLUTE_PATH);
110 }
111 $language = (new ReflectionClass(ilLanguage::class))->newInstanceWithoutConstructor();
112 $reflected = new ReflectionObject($language);
113 $reflected->getProperty('lang_key')->setValue($language, $lang_key);
114 $reflected->getProperty('lang_user')->setValue($language, $lang_key);
115 $reflected->getProperty('lang_default')->setValue($language, $lang_key);
116 $reflected->getProperty('log')->setValue($language, $this->createStub(ilLogger::class));
117
118 return $language;
119 }
120
122 private static function pluralCatalog(string $module, string $header, string $id, array $forms): TranslationCatalog
123 {
124 $catalog = new TranslationCatalog();
125 $catalog->setHeader('Content-Type', 'text/plain; charset=UTF-8');
126 if ($header !== '') {
127 $catalog->setHeader('Plural-Forms', $header);
128 }
129 $entry = new TranslationEntry($module, $id);
130 $entry->setPlural($id . 's', $forms);
131 $catalog->add($entry);
132
133 return $catalog;
134 }
135
137 {
138 $catalog = self::pluralCatalog('ntxt', 'nplurals=2; plural=(n != 1);', 'item', ['Eintrag', 'Einträge']);
140 $this->registerDirectoryManager($this->contributeModule('ntxt', $catalog));
141
142 $language = $this->buildLanguage();
143 $language->loadLanguageModule('ntxt');
144
145 $this->assertSame('Eintrag', $language->txt('item', 1));
146 $this->assertSame('Einträge', $language->txt('item', 0));
147 $this->assertSame('Einträge', $language->txt('item', 5));
148 $this->assertSame('Einträge', $language->txt('item', -5), 'a negative n counts like its absolute value');
149 }
150
152 {
153 $catalog = MigratedPoFixture::catalog('ntxt', ['plain' => 'Einfach']);
155 $this->registerDirectoryManager($this->contributeModule('ntxt', $catalog));
156
157 $language = $this->buildLanguage();
158 $language->loadLanguageModule('ntxt');
159
160 $this->assertSame('Einfach', $language->txt('plain', 1));
161 $this->assertSame('Einfach', $language->txt('plain', 5));
162 }
163
165 {
166 $language = $this->buildLanguage();
167
168 $this->assertSame($language->txt('unknown_topic'), $language->txt('unknown_topic', 5));
169 }
170
173 {
174 $catalog = self::pluralCatalog('ntxt', '', 'item', ['Eintrag', 'Einträge']);
176 $this->stubComponentLogger();
177 $this->registerDirectoryManager($this->contributeModule('ntxt', $catalog));
178
179 $language = $this->buildLanguage();
180 $language->loadLanguageModule('ntxt');
181
182 $this->assertSame('Eintrag', $language->txt('item', 1));
183 $this->assertSame('Einträge', $language->txt('item', 5));
184 }
185
188 {
189 $catalog = self::pluralCatalog('ntxt', 'nplurals=2; plural=(n != 1);', 'item', ['Eintrag', '']);
191 $this->registerDirectoryManager($this->contributeModule('ntxt', $catalog));
192
193 $language = $this->buildLanguage();
194 $language->loadLanguageModule('ntxt');
195
196 // an empty default form falls back to form 0, which txt() and the n=5 fallback with $n both serve
197 $this->assertSame('Eintrag', $language->txt('item'));
198 $this->assertSame('Eintrag', $language->txt('item', 5));
199 }
200
203 {
204 $plural = self::pluralCatalog('ntxt_a', 'nplurals=2; plural=(n != 1);', 'shared', ['Eintrag', 'Einträge']);
205 $overwritten = MigratedPoFixture::catalog('ntxt_b', ['shared' => 'Überschrieben']);
208 $this->contributeModule('ntxt_a', $plural),
209 $this->contributeModule('ntxt_b', $overwritten)
210 );
211
212 $language = $this->buildLanguage();
213 $language->loadLanguageModule('ntxt_a');
214 $language->loadLanguageModule('ntxt_b');
215
216 $this->assertSame('Überschrieben', $language->txt('shared', 5));
217 }
218
220 {
221 $shipped = self::pluralCatalog('ntxt', 'nplurals=2; plural=(n != 1);', 'item', ['Eintrag', 'Einträge']);
222 $overlay = self::pluralCatalog('ntxt', 'nplurals=2; plural=(n != 1);', 'item', ['Datensatz', 'Datensätze']);
224 $this->registerDirectoryManager($this->contributeModule('ntxt', $shipped, $overlay));
225
226 $language = $this->buildLanguage();
227 $language->loadLanguageModule('ntxt');
228
229 $this->assertSame('Datensatz', $language->txt('item', 1));
230 $this->assertSame('Datensätze', $language->txt('item', 5));
231 }
232}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
An in-memory gettext catalog (header block plus messages) and the only place of the component that re...
One message of a TranslationCatalog (a msgctxt/msgid/msgstr block of a .po file).
static removeShippedDirectory(string $relative_path)
static ensureClientDataDirDefinedOrSkip(\PHPUnit\Framework\TestCase $test)
Guards every fixture that writes under CLIENT_DATA_DIR: a full-suite run may have defined it as the r...
static writePair(string $base_path, TranslationCatalog $catalog)
Writes "<base>.po" and, like MigratedLanguageFileSync::sync(), its compiled revision named by current...
static directory(string $prefix, string $path, bool $local=false)
static catalog(string $module, array $entries)
static removeDirectory(string $directory)
static writeShippedPo(string $relative_path, string $module, string $lang_key, TranslationCatalog $catalog)
Writes $catalog as the shipped .po: a module only counts as migrated while that exists.
static build(LanguageFileDirectoryManager $manager, string $ilias_absolute_path)
Builds the shipped .po files of $manager below $ilias_absolute_path into the artifact directory of re...
static resetRuntime(?string $artifact_directory=null)
Forgets the static state of the runtime read path and points build and runtime at $artifact_directory...
ilLanguage::txt() with $n, the plural-aware form.
contributeModule(string $module, TranslationCatalog $catalog, ?TranslationCatalog $overlay=null)
Contributes a migrated module whose shipped .po (and, if it differs, overlay .mo) is $catalog,...
registerDirectoryManager(LanguageFileDirectory ... $contributed)
string $fixture_directory
testALaterModuleOverwritingTheIdentifierWinsOverTheEarlierPluralForms()
A later module overwriting the identifier with a plain value must win with $n too.
testFallsBackToTxtForATopicThatWasNeverLoadedAtAll()
testFallsBackToTxtForAnOrdinarySingularIdentifier()
buildLanguage(string $lang_key='de')
testUsesTheGermanicRuleWhenThePluralFormsHeaderIsMissing()
Without a "Plural-Forms" header the Germanic rule (n==1 -> form 0, else 1) applies instead of failing...
stubComponentLogger()
Logged problems (e.g.
testAnOverlayReplacingThePluralFormsIsUsedForFormSelection()
testSelectsTheFormThePluralRuleOfTheLanguagePicksForN()
testFallsBackToTxtWhenTheSelectedFormIsEmpty()
An empty selected form falls back to txt() rather than returning an empty string.
static pluralCatalog(string $module, string $header, string $id, array $forms)
Class ilLanguageBaseTest.
setGlobalVariable(string $name, $value)
language handling
const CLIENT_DATA_DIR
Definition: constants.php:46
if(!isset($arguments[0])) if(count( $arguments) > 3) if(! $remove_from_lang &&isset($arguments[2]) &&!is_dir($arguments[2])) $module
A directory of language files with a path and a prefix for them.
global $DIC
Definition: shib_login.php:26