PoFileParserTest.php 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  5. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  6. *
  7. * Licensed under The MIT License
  8. * For full copyright and license information, please see the LICENSE.txt
  9. * Redistributions of files must retain the above copyright notice.
  10. *
  11. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  12. * @link https://cakephp.org CakePHP(tm) Project
  13. * @since 3.0.0
  14. * @license https://opensource.org/licenses/mit-license.php MIT License
  15. */
  16. namespace Cake\Test\TestCase\I18n\Parser;
  17. use Aura\Intl\Package;
  18. use Cake\Cache\Cache;
  19. use Cake\I18n\I18n;
  20. use Cake\I18n\Parser\PoFileParser;
  21. use Cake\TestSuite\TestCase;
  22. /**
  23. * Tests the PoFileLoader
  24. */
  25. class PoFileParserTest extends TestCase
  26. {
  27. protected $locale;
  28. /**
  29. * Set Up
  30. *
  31. * @return void
  32. */
  33. public function setUp()
  34. {
  35. parent::setUp();
  36. $this->locale = I18n::getLocale();
  37. }
  38. /**
  39. * Tear down method
  40. *
  41. * @return void
  42. */
  43. public function tearDown()
  44. {
  45. parent::tearDown();
  46. I18n::clear();
  47. I18n::setLocale($this->locale);
  48. Cache::clear('_cake_core_');
  49. }
  50. /**
  51. * Tests parsing a file with plurals and message context
  52. *
  53. * @return void
  54. */
  55. public function testParse()
  56. {
  57. $parser = new PoFileParser();
  58. $file = APP . 'Locale' . DS . 'rule_1_po' . DS . 'default.po';
  59. $messages = $parser->parse($file);
  60. $this->assertCount(8, $messages);
  61. $expected = [
  62. 'Plural Rule 1' => [
  63. '_context' => [
  64. '' => 'Plural Rule 1 (translated)',
  65. ],
  66. ],
  67. '%d = 1' => [
  68. '_context' => [
  69. 'This is the context' => 'First Context translation',
  70. 'Another Context' => '%d = 1 (translated)',
  71. ],
  72. ],
  73. 'p:%d = 0 or > 1' => [
  74. '_context' => [
  75. 'Another Context' => [
  76. 0 => '%d = 1 (translated)',
  77. 1 => '%d = 0 or > 1 (translated)',
  78. ],
  79. ],
  80. ],
  81. '%-5d = 1' => [
  82. '_context' => [
  83. '' => '%-5d = 1 (translated)',
  84. ],
  85. ],
  86. 'p:%-5d = 0 or > 1' => [
  87. '_context' => [
  88. '' => [
  89. 0 => '%-5d = 1 (translated)',
  90. 1 => '',
  91. 2 => '',
  92. 3 => '',
  93. 4 => '%-5d = 0 or > 1 (translated)',
  94. ],
  95. ],
  96. ],
  97. '%d = 2' => [
  98. '_context' => [
  99. 'This is another translated context' => 'First Context translation',
  100. ],
  101. ],
  102. '%-6d = 3' => [
  103. '_context' => [
  104. '' => '%-6d = 1 (translated)',
  105. ],
  106. ],
  107. 'p:%-6d = 0 or > 1' => [
  108. '_context' => [
  109. '' => [
  110. 0 => '%-6d = 1 (translated)',
  111. 1 => '',
  112. 2 => '',
  113. 3 => '',
  114. 4 => '%-6d = 0 or > 1 (translated)',
  115. ],
  116. ],
  117. ],
  118. ];
  119. $this->assertEquals($expected, $messages);
  120. }
  121. /**
  122. * Tests parsing a file with multiline keys and values
  123. *
  124. * @return void
  125. */
  126. public function testParseMultiLine()
  127. {
  128. $parser = new PoFileParser();
  129. $file = APP . 'Locale' . DS . 'en' . DS . 'default.po';
  130. $messages = $parser->parse($file);
  131. $this->assertCount(12, $messages);
  132. $this->assertTextEquals("v\nsecond line", $messages["valid\nsecond line"]['_context']['']);
  133. }
  134. /**
  135. * Test parsing a file with quoted strings
  136. *
  137. * @return void
  138. */
  139. public function testQuotedString()
  140. {
  141. $parser = new PoFileParser();
  142. $file = APP . 'Locale' . DS . 'en' . DS . 'default.po';
  143. $messages = $parser->parse($file);
  144. $this->assertTextEquals('this is a "quoted string" (translated)', $messages['this is a "quoted string"']['_context']['']);
  145. }
  146. /**
  147. * Test parsing a file with message context on some msgid values.
  148. *
  149. * This behavior is not ideal, but more thorough solutions
  150. * would break compatibility. Perhaps this is something we can
  151. * reconsider in 4.x
  152. *
  153. * @return void
  154. */
  155. public function testParseContextOnSomeMessages()
  156. {
  157. $parser = new PoFileParser();
  158. $file = APP . 'Locale' . DS . 'en' . DS . 'context.po';
  159. $messages = $parser->parse($file);
  160. I18n::setTranslator('default', function () use ($messages) {
  161. $package = new Package('default');
  162. $package->setMessages($messages);
  163. return $package;
  164. }, 'en_CA');
  165. $this->assertSame('En cours', $messages['Pending']['_context']['']);
  166. $this->assertSame('En cours - context', $messages['Pending']['_context']['Pay status']);
  167. $this->assertSame('En resolved', $messages['Resolved']['_context']['']);
  168. $this->assertSame('En resolved - context', $messages['Resolved']['_context']['Pay status']);
  169. $key = '{0,plural,=0{Je suis}=1{Je suis}=2{Nous sommes} other{Nous sommes}}';
  170. $this->assertContains("I've", $messages[$key]['_context']['origin']);
  171. // Confirm actual behavior
  172. I18n::setLocale('en_CA');
  173. $this->assertSame('En cours', __('Pending'));
  174. $this->assertSame('En cours - context', __x('Pay status', 'Pending'));
  175. $this->assertSame('En resolved', __('Resolved'));
  176. $this->assertSame('En resolved - context', __x('Pay status', 'Resolved'));
  177. $this->assertSame("I've", __x('origin', $key, [1]));
  178. $this->assertSame("We are", __x('origin', $key, [3]));
  179. }
  180. /**
  181. * Test parsing context based messages
  182. *
  183. * @return void
  184. */
  185. public function testParseContextMessages()
  186. {
  187. $parser = new PoFileParser();
  188. $file = APP . 'Locale' . DS . 'en' . DS . 'context.po';
  189. $messages = $parser->parse($file);
  190. I18n::setTranslator('default', function () use ($messages) {
  191. $package = new Package('default');
  192. $package->setMessages($messages);
  193. return $package;
  194. }, 'en_US');
  195. // Check translated messages
  196. I18n::setLocale('en_US');
  197. $this->assertSame('Titel mit Kontext', __x('context', 'title'));
  198. $this->assertSame('Titel mit anderem Kontext', __x('another_context', 'title'));
  199. $this->assertSame('Titel ohne Kontext', __('title'));
  200. }
  201. /**
  202. * Test parsing plurals
  203. *
  204. * @return void
  205. */
  206. public function testPlurals()
  207. {
  208. $parser = new PoFileParser();
  209. $file = APP . 'Locale' . DS . 'de' . DS . 'wa.po';
  210. $messages = $parser->parse($file);
  211. I18n::getTranslator('default', 'de_DE', function () use ($messages) {
  212. $package = new Package('default');
  213. $package->setMessages($messages);
  214. return $package;
  215. });
  216. // Check translated messages
  217. I18n::setLocale('de_DE');
  218. $this->assertEquals('Standorte', __d('wa', 'Locations'));
  219. I18n::setLocale('en_EN');
  220. $this->assertEquals('Locations', __d('wa', 'Locations'));
  221. }
  222. }