Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\Tests\locale\Unit;
|
Chris@0
|
4
|
Chris@18
|
5 use Drupal\Component\Gettext\PoItem;
|
Chris@0
|
6 use Drupal\Core\DependencyInjection\ContainerBuilder;
|
Chris@0
|
7 use Drupal\locale\LocaleLookup;
|
Chris@0
|
8 use Drupal\Tests\UnitTestCase;
|
Chris@0
|
9 use Symfony\Component\HttpFoundation\Request;
|
Chris@0
|
10 use Symfony\Component\HttpFoundation\RequestStack;
|
Chris@0
|
11
|
Chris@0
|
12 /**
|
Chris@0
|
13 * @coversDefaultClass \Drupal\locale\LocaleLookup
|
Chris@0
|
14 * @group locale
|
Chris@0
|
15 */
|
Chris@0
|
16 class LocaleLookupTest extends UnitTestCase {
|
Chris@0
|
17
|
Chris@0
|
18 /**
|
Chris@0
|
19 * A mocked storage to use when instantiating LocaleTranslation objects.
|
Chris@0
|
20 *
|
Chris@0
|
21 * @var \Drupal\locale\StringStorageInterface|\PHPUnit_Framework_MockObject_MockObject
|
Chris@0
|
22 */
|
Chris@0
|
23 protected $storage;
|
Chris@0
|
24
|
Chris@0
|
25 /**
|
Chris@0
|
26 * A mocked cache object.
|
Chris@0
|
27 *
|
Chris@0
|
28 * @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
|
Chris@0
|
29 */
|
Chris@0
|
30 protected $cache;
|
Chris@0
|
31
|
Chris@0
|
32 /**
|
Chris@0
|
33 * A mocked lock object.
|
Chris@0
|
34 *
|
Chris@0
|
35 * @var \Drupal\Core\Lock\LockBackendInterface|\PHPUnit_Framework_MockObject_MockObject
|
Chris@0
|
36 */
|
Chris@0
|
37 protected $lock;
|
Chris@0
|
38
|
Chris@0
|
39 /**
|
Chris@0
|
40 * A mocked user object built from AccountInterface.
|
Chris@0
|
41 *
|
Chris@0
|
42 * @var \Drupal\Core\Session\AccountInterface|\PHPUnit_Framework_MockObject_MockObject
|
Chris@0
|
43 */
|
Chris@0
|
44 protected $user;
|
Chris@0
|
45
|
Chris@0
|
46 /**
|
Chris@0
|
47 * A mocked config factory built with UnitTestCase::getConfigFactoryStub().
|
Chris@0
|
48 *
|
Chris@0
|
49 * @var \Drupal\Core\Config\ConfigFactory|\PHPUnit_Framework_MockObject_MockBuilder
|
Chris@0
|
50 */
|
Chris@0
|
51 protected $configFactory;
|
Chris@0
|
52
|
Chris@0
|
53 /**
|
Chris@0
|
54 * A mocked language manager built from LanguageManagerInterface.
|
Chris@0
|
55 *
|
Chris@0
|
56 * @var \Drupal\Core\Language\LanguageManagerInterface|\PHPUnit_Framework_MockObject_MockObject
|
Chris@0
|
57 */
|
Chris@0
|
58 protected $languageManager;
|
Chris@0
|
59
|
Chris@0
|
60 /**
|
Chris@0
|
61 * The request stack.
|
Chris@0
|
62 *
|
Chris@0
|
63 * @var \Symfony\Component\HttpFoundation\RequestStack
|
Chris@0
|
64 */
|
Chris@0
|
65 protected $requestStack;
|
Chris@0
|
66
|
Chris@0
|
67 /**
|
Chris@0
|
68 * {@inheritdoc}
|
Chris@0
|
69 */
|
Chris@0
|
70 protected function setUp() {
|
Chris@0
|
71 $this->storage = $this->getMock('Drupal\locale\StringStorageInterface');
|
Chris@0
|
72 $this->cache = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
|
Chris@0
|
73 $this->lock = $this->getMock('Drupal\Core\Lock\LockBackendInterface');
|
Chris@0
|
74 $this->lock->expects($this->never())
|
Chris@0
|
75 ->method($this->anything());
|
Chris@0
|
76
|
Chris@0
|
77 $this->user = $this->getMock('Drupal\Core\Session\AccountInterface');
|
Chris@0
|
78 $this->user->expects($this->any())
|
Chris@0
|
79 ->method('getRoles')
|
Chris@0
|
80 ->will($this->returnValue(['anonymous']));
|
Chris@0
|
81
|
Chris@0
|
82 $this->configFactory = $this->getConfigFactoryStub(['locale.settings' => ['cache_strings' => FALSE]]);
|
Chris@0
|
83
|
Chris@0
|
84 $this->languageManager = $this->getMock('Drupal\Core\Language\LanguageManagerInterface');
|
Chris@0
|
85 $this->requestStack = new RequestStack();
|
Chris@0
|
86
|
Chris@0
|
87 $container = new ContainerBuilder();
|
Chris@0
|
88 $container->set('current_user', $this->user);
|
Chris@0
|
89 \Drupal::setContainer($container);
|
Chris@0
|
90 }
|
Chris@0
|
91
|
Chris@0
|
92 /**
|
Chris@0
|
93 * Tests locale lookups without fallback.
|
Chris@0
|
94 *
|
Chris@0
|
95 * @covers ::resolveCacheMiss
|
Chris@0
|
96 */
|
Chris@0
|
97 public function testResolveCacheMissWithoutFallback() {
|
Chris@0
|
98 $args = [
|
Chris@0
|
99 'language' => 'en',
|
Chris@0
|
100 'source' => 'test',
|
Chris@0
|
101 'context' => 'irrelevant',
|
Chris@0
|
102 ];
|
Chris@0
|
103
|
Chris@0
|
104 $result = (object) [
|
Chris@0
|
105 'translation' => 'test',
|
Chris@0
|
106 ];
|
Chris@0
|
107
|
Chris@0
|
108 $this->cache->expects($this->once())
|
Chris@0
|
109 ->method('get')
|
Chris@0
|
110 ->with('locale:en:irrelevant:anonymous', FALSE);
|
Chris@0
|
111
|
Chris@0
|
112 $this->storage->expects($this->once())
|
Chris@0
|
113 ->method('findTranslation')
|
Chris@0
|
114 ->with($this->equalTo($args))
|
Chris@0
|
115 ->will($this->returnValue($result));
|
Chris@0
|
116
|
Chris@0
|
117 $locale_lookup = $this->getMockBuilder('Drupal\locale\LocaleLookup')
|
Chris@0
|
118 ->setConstructorArgs(['en', 'irrelevant', $this->storage, $this->cache, $this->lock, $this->configFactory, $this->languageManager, $this->requestStack])
|
Chris@0
|
119 ->setMethods(['persist'])
|
Chris@0
|
120 ->getMock();
|
Chris@0
|
121 $locale_lookup->expects($this->never())
|
Chris@0
|
122 ->method('persist');
|
Chris@0
|
123 $this->assertSame('test', $locale_lookup->get('test'));
|
Chris@0
|
124 }
|
Chris@0
|
125
|
Chris@0
|
126 /**
|
Chris@0
|
127 * Tests locale lookups with fallback.
|
Chris@0
|
128 *
|
Chris@0
|
129 * Note that context is irrelevant here. It is not used but it is required.
|
Chris@0
|
130 *
|
Chris@0
|
131 * @covers ::resolveCacheMiss
|
Chris@0
|
132 *
|
Chris@0
|
133 * @dataProvider resolveCacheMissWithFallbackProvider
|
Chris@0
|
134 */
|
Chris@0
|
135 public function testResolveCacheMissWithFallback($langcode, $string, $context, $expected) {
|
Chris@0
|
136 // These are fake words!
|
Chris@0
|
137 $translations = [
|
Chris@0
|
138 'en' => [
|
Chris@0
|
139 'test' => 'test',
|
Chris@0
|
140 'fake' => 'fake',
|
Chris@0
|
141 'missing pl' => 'missing pl',
|
Chris@0
|
142 'missing cs' => 'missing cs',
|
Chris@0
|
143 'missing both' => 'missing both',
|
Chris@0
|
144 ],
|
Chris@0
|
145 'pl' => [
|
Chris@0
|
146 'test' => 'test po polsku',
|
Chris@0
|
147 'fake' => 'ściema',
|
Chris@0
|
148 'missing cs' => 'zaginiony czech',
|
Chris@0
|
149 ],
|
Chris@0
|
150 'cs' => [
|
Chris@0
|
151 'test' => 'test v české',
|
Chris@0
|
152 'fake' => 'falešný',
|
Chris@0
|
153 'missing pl' => 'chybějící pl',
|
Chris@0
|
154 ],
|
Chris@0
|
155 ];
|
Chris@0
|
156 $this->storage->expects($this->any())
|
Chris@0
|
157 ->method('findTranslation')
|
Chris@0
|
158 ->will($this->returnCallback(function ($argument) use ($translations) {
|
Chris@0
|
159 if (isset($translations[$argument['language']][$argument['source']])) {
|
Chris@0
|
160 return (object) ['translation' => $translations[$argument['language']][$argument['source']]];
|
Chris@0
|
161 }
|
Chris@0
|
162 return TRUE;
|
Chris@0
|
163 }));
|
Chris@0
|
164
|
Chris@0
|
165 $this->languageManager->expects($this->any())
|
Chris@0
|
166 ->method('getFallbackCandidates')
|
Chris@0
|
167 ->will($this->returnCallback(function (array $context = []) {
|
Chris@0
|
168 switch ($context['langcode']) {
|
Chris@0
|
169 case 'pl':
|
Chris@0
|
170 return ['cs', 'en'];
|
Chris@0
|
171
|
Chris@0
|
172 case 'cs':
|
Chris@0
|
173 return ['en'];
|
Chris@0
|
174
|
Chris@0
|
175 default:
|
Chris@0
|
176 return [];
|
Chris@0
|
177 }
|
Chris@0
|
178 }));
|
Chris@0
|
179
|
Chris@0
|
180 $this->cache->expects($this->once())
|
Chris@0
|
181 ->method('get')
|
Chris@0
|
182 ->with('locale:' . $langcode . ':' . $context . ':anonymous', FALSE);
|
Chris@0
|
183
|
Chris@0
|
184 $locale_lookup = new LocaleLookup($langcode, $context, $this->storage, $this->cache, $this->lock, $this->configFactory, $this->languageManager, $this->requestStack);
|
Chris@0
|
185 $this->assertSame($expected, $locale_lookup->get($string));
|
Chris@0
|
186 }
|
Chris@0
|
187
|
Chris@0
|
188 /**
|
Chris@0
|
189 * Provides test data for testResolveCacheMissWithFallback().
|
Chris@0
|
190 */
|
Chris@0
|
191 public function resolveCacheMissWithFallbackProvider() {
|
Chris@0
|
192 return [
|
Chris@0
|
193 ['cs', 'test', 'irrelevant', 'test v české'],
|
Chris@0
|
194 ['cs', 'fake', 'irrelevant', 'falešný'],
|
Chris@0
|
195 ['cs', 'missing pl', 'irrelevant', 'chybějící pl'],
|
Chris@0
|
196 ['cs', 'missing cs', 'irrelevant', 'missing cs'],
|
Chris@0
|
197 ['cs', 'missing both', 'irrelevant', 'missing both'],
|
Chris@0
|
198
|
Chris@0
|
199 // Testing PL with fallback to cs, en.
|
Chris@0
|
200 ['pl', 'test', 'irrelevant', 'test po polsku'],
|
Chris@0
|
201 ['pl', 'fake', 'irrelevant', 'ściema'],
|
Chris@0
|
202 ['pl', 'missing pl', 'irrelevant', 'chybějící pl'],
|
Chris@0
|
203 ['pl', 'missing cs', 'irrelevant', 'zaginiony czech'],
|
Chris@0
|
204 ['pl', 'missing both', 'irrelevant', 'missing both'],
|
Chris@0
|
205 ];
|
Chris@0
|
206 }
|
Chris@0
|
207
|
Chris@0
|
208 /**
|
Chris@0
|
209 * Tests locale lookups with persistent tracking.
|
Chris@0
|
210 *
|
Chris@0
|
211 * @covers ::resolveCacheMiss
|
Chris@0
|
212 */
|
Chris@0
|
213 public function testResolveCacheMissWithPersist() {
|
Chris@0
|
214 $args = [
|
Chris@0
|
215 'language' => 'en',
|
Chris@0
|
216 'source' => 'test',
|
Chris@0
|
217 'context' => 'irrelevant',
|
Chris@0
|
218 ];
|
Chris@0
|
219
|
Chris@0
|
220 $result = (object) [
|
Chris@0
|
221 'translation' => 'test',
|
Chris@0
|
222 ];
|
Chris@0
|
223
|
Chris@0
|
224 $this->storage->expects($this->once())
|
Chris@0
|
225 ->method('findTranslation')
|
Chris@0
|
226 ->with($this->equalTo($args))
|
Chris@0
|
227 ->will($this->returnValue($result));
|
Chris@0
|
228
|
Chris@0
|
229 $this->configFactory = $this->getConfigFactoryStub(['locale.settings' => ['cache_strings' => TRUE]]);
|
Chris@0
|
230 $locale_lookup = $this->getMockBuilder('Drupal\locale\LocaleLookup')
|
Chris@0
|
231 ->setConstructorArgs(['en', 'irrelevant', $this->storage, $this->cache, $this->lock, $this->configFactory, $this->languageManager, $this->requestStack])
|
Chris@0
|
232 ->setMethods(['persist'])
|
Chris@0
|
233 ->getMock();
|
Chris@0
|
234 $locale_lookup->expects($this->once())
|
Chris@0
|
235 ->method('persist');
|
Chris@0
|
236
|
Chris@0
|
237 $this->assertSame('test', $locale_lookup->get('test'));
|
Chris@0
|
238 }
|
Chris@0
|
239
|
Chris@0
|
240 /**
|
Chris@0
|
241 * Tests locale lookups without a found translation.
|
Chris@0
|
242 *
|
Chris@0
|
243 * @covers ::resolveCacheMiss
|
Chris@0
|
244 */
|
Chris@0
|
245 public function testResolveCacheMissNoTranslation() {
|
Chris@0
|
246 $string = $this->getMock('Drupal\locale\StringInterface');
|
Chris@0
|
247 $string->expects($this->once())
|
Chris@0
|
248 ->method('addLocation')
|
Chris@0
|
249 ->will($this->returnSelf());
|
Chris@0
|
250 $this->storage->expects($this->once())
|
Chris@0
|
251 ->method('findTranslation')
|
Chris@0
|
252 ->will($this->returnValue(NULL));
|
Chris@0
|
253 $this->storage->expects($this->once())
|
Chris@0
|
254 ->method('createString')
|
Chris@0
|
255 ->will($this->returnValue($string));
|
Chris@0
|
256
|
Chris@0
|
257 $request = Request::create('/test');
|
Chris@0
|
258 $this->requestStack->push($request);
|
Chris@0
|
259
|
Chris@0
|
260 $locale_lookup = $this->getMockBuilder('Drupal\locale\LocaleLookup')
|
Chris@0
|
261 ->setConstructorArgs(['en', 'irrelevant', $this->storage, $this->cache, $this->lock, $this->configFactory, $this->languageManager, $this->requestStack])
|
Chris@0
|
262 ->setMethods(['persist'])
|
Chris@0
|
263 ->getMock();
|
Chris@0
|
264 $locale_lookup->expects($this->never())
|
Chris@0
|
265 ->method('persist');
|
Chris@0
|
266
|
Chris@0
|
267 $this->assertTrue($locale_lookup->get('test'));
|
Chris@0
|
268 }
|
Chris@0
|
269
|
Chris@12
|
270 /**
|
Chris@12
|
271 * Tests locale lookups with old plural style of translations.
|
Chris@12
|
272 *
|
Chris@12
|
273 * @param array $translations
|
Chris@12
|
274 * The source with translations.
|
Chris@12
|
275 * @param string $langcode
|
Chris@12
|
276 * The language code of translation string.
|
Chris@12
|
277 * @param string $string
|
Chris@12
|
278 * The string for translation.
|
Chris@12
|
279 * @param bool $is_fix
|
Chris@12
|
280 * The flag about expected fix translation.
|
Chris@12
|
281 *
|
Chris@12
|
282 * @covers ::resolveCacheMiss
|
Chris@12
|
283 * @dataProvider providerFixOldPluralTranslationProvider
|
Chris@12
|
284 */
|
Chris@12
|
285 public function testFixOldPluralStyleTranslations($translations, $langcode, $string, $is_fix) {
|
Chris@12
|
286 $this->storage->expects($this->any())
|
Chris@12
|
287 ->method('findTranslation')
|
Chris@12
|
288 ->will($this->returnCallback(function ($argument) use ($translations) {
|
Chris@12
|
289 if (isset($translations[$argument['language']][$argument['source']])) {
|
Chris@12
|
290 return (object) ['translation' => $translations[$argument['language']][$argument['source']]];
|
Chris@12
|
291 }
|
Chris@12
|
292 return TRUE;
|
Chris@12
|
293 }));
|
Chris@12
|
294 $this->languageManager->expects($this->any())
|
Chris@12
|
295 ->method('getFallbackCandidates')
|
Chris@12
|
296 ->will($this->returnCallback(function (array $context = []) {
|
Chris@12
|
297 switch ($context['langcode']) {
|
Chris@12
|
298 case 'by':
|
Chris@12
|
299 return ['ru'];
|
Chris@12
|
300 }
|
Chris@12
|
301 }));
|
Chris@12
|
302 $this->cache->expects($this->once())
|
Chris@12
|
303 ->method('get')
|
Chris@12
|
304 ->with('locale:' . $langcode . '::anonymous', FALSE);
|
Chris@12
|
305
|
Chris@12
|
306 $locale_lookup = new LocaleLookup($langcode, '', $this->storage, $this->cache, $this->lock, $this->configFactory, $this->languageManager, $this->requestStack);
|
Chris@12
|
307 $this->assertSame($is_fix, strpos($locale_lookup->get($string), '@count[2]') === FALSE);
|
Chris@12
|
308 }
|
Chris@12
|
309
|
Chris@12
|
310 /**
|
Chris@12
|
311 * Provides test data for testResolveCacheMissWithFallback().
|
Chris@12
|
312 */
|
Chris@12
|
313 public function providerFixOldPluralTranslationProvider() {
|
Chris@12
|
314 $translations = [
|
Chris@12
|
315 'by' => [
|
Chris@12
|
316 'word1' => '@count[2] word-by',
|
Chris@18
|
317 'word2' => implode(PoItem::DELIMITER, ['word-by', '@count[2] word-by']),
|
Chris@12
|
318 ],
|
Chris@12
|
319 'ru' => [
|
Chris@12
|
320 'word3' => '@count[2] word-ru',
|
Chris@18
|
321 'word4' => implode(PoItem::DELIMITER, ['word-ru', '@count[2] word-ru']),
|
Chris@12
|
322 ],
|
Chris@12
|
323 ];
|
Chris@12
|
324 return [
|
Chris@12
|
325 'no-plural' => [$translations, 'by', 'word1', FALSE],
|
Chris@12
|
326 'no-plural from other language' => [$translations, 'by', 'word3', FALSE],
|
Chris@12
|
327 'plural' => [$translations, 'by', 'word2', TRUE],
|
Chris@12
|
328 'plural from other language' => [$translations, 'by', 'word4', TRUE],
|
Chris@12
|
329 ];
|
Chris@12
|
330 }
|
Chris@12
|
331
|
Chris@0
|
332 }
|