l10nSpec.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /**
  2. * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
  3. * SPDX-FileCopyrightText: 2014 ownCloud Inc.
  4. * SPDX-License-Identifier: AGPL-3.0-or-later
  5. */
  6. describe('OC.L10N tests', function() {
  7. var TEST_APP = 'jsunittestapp';
  8. beforeEach(function() {
  9. window._oc_appswebroots[TEST_APP] = OC.getRootPath() + '/apps3/jsunittestapp';
  10. window.OC = window.OC ?? {}
  11. window.OC.appswebroots = window.OC.appswebroots || {}
  12. window.OC.appswebroots[TEST_APP] = OC.getRootPath() + '/apps3/jsunittestapp'
  13. });
  14. afterEach(function() {
  15. OC.L10N._unregister(TEST_APP);
  16. delete window._oc_appswebroots[TEST_APP];
  17. delete window.OC.appswebroots[TEST_APP];
  18. });
  19. describe('text translation', function() {
  20. beforeEach(function() {
  21. spyOn(console, 'warn');
  22. OC.L10N.register(TEST_APP, {
  23. 'Hello world!': 'Hallo Welt!',
  24. 'Hello {name}, the weather is {weather}': 'Hallo {name}, das Wetter ist {weather}',
  25. 'sunny': 'sonnig'
  26. });
  27. });
  28. it('returns untranslated text when no bundle exists', function() {
  29. OC.L10N._unregister(TEST_APP);
  30. expect(t(TEST_APP, 'unknown text')).toEqual('unknown text');
  31. });
  32. it('returns untranslated text when no key exists', function() {
  33. expect(t(TEST_APP, 'unknown text')).toEqual('unknown text');
  34. });
  35. it('returns translated text when key exists', function() {
  36. expect(t(TEST_APP, 'Hello world!')).toEqual('Hallo Welt!');
  37. });
  38. it('returns translated text with placeholder', function() {
  39. expect(
  40. t(TEST_APP, 'Hello {name}, the weather is {weather}', {name: 'Steve', weather: t(TEST_APP, 'sunny')})
  41. ).toEqual('Hallo Steve, das Wetter ist sonnig');
  42. });
  43. it('returns text with escaped placeholder', function() {
  44. expect(
  45. t(TEST_APP, 'Hello {name}', {name: '<strong>Steve</strong>'})
  46. ).toEqual('Hello &lt;strong&gt;Steve&lt;/strong&gt;');
  47. });
  48. it('returns text with not escaped placeholder', function() {
  49. expect(
  50. t(TEST_APP, 'Hello {name}', {name: '<strong>Steve</strong>'}, null, {escape: false})
  51. ).toEqual('Hello <strong>Steve</strong>');
  52. });
  53. it('uses DOMPurify to escape the text', function() {
  54. expect(
  55. t(TEST_APP, '<strong>These are your search results<script>alert(1)</script></strong>', null, {escape: false})
  56. ).toEqual('<strong>These are your search results</strong>');
  57. });
  58. it('keeps old texts when registering existing bundle', function() {
  59. OC.L10N.register(TEST_APP, {
  60. 'sunny': 'sonnig',
  61. 'new': 'neu'
  62. });
  63. expect(t(TEST_APP, 'sunny')).toEqual('sonnig');
  64. expect(t(TEST_APP, 'new')).toEqual('neu');
  65. });
  66. });
  67. describe('plurals', function() {
  68. function checkPlurals() {
  69. expect(
  70. n(TEST_APP, 'download %n file', 'download %n files', 0)
  71. ).toEqual('0 Dateien herunterladen');
  72. expect(
  73. n(TEST_APP, 'download %n file', 'download %n files', 1)
  74. ).toEqual('1 Datei herunterladen');
  75. expect(
  76. n(TEST_APP, 'download %n file', 'download %n files', 2)
  77. ).toEqual('2 Dateien herunterladen');
  78. expect(
  79. n(TEST_APP, 'download %n file', 'download %n files', 1024)
  80. ).toEqual('1024 Dateien herunterladen');
  81. }
  82. it('generates plural for default text when translation does not exist', function() {
  83. spyOn(console, 'warn');
  84. OC.L10N.register(TEST_APP, {
  85. });
  86. expect(
  87. n(TEST_APP, 'download %n file', 'download %n files', 0)
  88. ).toEqual('download 0 files');
  89. expect(
  90. n(TEST_APP, 'download %n file', 'download %n files', 1)
  91. ).toEqual('download 1 file');
  92. expect(
  93. n(TEST_APP, 'download %n file', 'download %n files', 2)
  94. ).toEqual('download 2 files');
  95. expect(
  96. n(TEST_APP, 'download %n file', 'download %n files', 1024)
  97. ).toEqual('download 1024 files');
  98. });
  99. it('generates plural with default function when no forms specified', function() {
  100. spyOn(console, 'warn');
  101. OC.L10N.register(TEST_APP, {
  102. '_download %n file_::_download %n files_':
  103. ['%n Datei herunterladen', '%n Dateien herunterladen']
  104. });
  105. checkPlurals();
  106. });
  107. });
  108. describe('async loading of translations', function() {
  109. afterEach(() => {
  110. document.documentElement.removeAttribute('data-locale')
  111. })
  112. it('loads bundle for given app and calls callback', function(done) {
  113. document.documentElement.setAttribute('data-locale', 'zh_CN')
  114. var callbackStub = sinon.stub();
  115. var promiseStub = sinon.stub();
  116. var loading = OC.L10N.load(TEST_APP, callbackStub);
  117. expect(callbackStub.notCalled).toEqual(true);
  118. var req = fakeServer.requests[0];
  119. console.warn('fff-', window.OC.appswebroots)
  120. loading
  121. .then(promiseStub)
  122. .then(function() {
  123. expect(fakeServer.requests.length).toEqual(1);
  124. expect(req.url).toEqual(
  125. OC.getRootPath() + '/apps3/' + TEST_APP + '/l10n/zh_CN.json'
  126. );
  127. expect(callbackStub.calledOnce).toEqual(true);
  128. expect(promiseStub.calledOnce).toEqual(true);
  129. expect(t(TEST_APP, 'Hello world!')).toEqual('你好世界!');
  130. })
  131. .then(done)
  132. .catch(e => expect(e).toBe('No error expected!'));
  133. expect(promiseStub.notCalled).toEqual(true);
  134. req.respond(
  135. 200,
  136. { 'Content-Type': 'application/json' },
  137. JSON.stringify({
  138. translations: {'Hello world!': '你好世界!'},
  139. pluralForm: 'nplurals=2; plural=(n != 1);'
  140. })
  141. );
  142. });
  143. it('calls callback if translation already available', function(done) {
  144. var callbackStub = sinon.stub();
  145. spyOn(console, 'warn');
  146. OC.L10N.register(TEST_APP, {
  147. 'Hello world!': 'Hallo Welt!'
  148. });
  149. OC.L10N.load(TEST_APP, callbackStub)
  150. .then(function() {
  151. expect(callbackStub.calledOnce).toEqual(true);
  152. expect(fakeServer.requests.length).toEqual(0);
  153. })
  154. .then(done);
  155. });
  156. it('calls callback if locale is en', function(done) {
  157. var callbackStub = sinon.stub();
  158. OC.L10N.load(TEST_APP, callbackStub)
  159. .then(function() {
  160. expect(callbackStub.calledOnce).toEqual(true);
  161. expect(fakeServer.requests.length).toEqual(0);
  162. })
  163. .then(done)
  164. .catch(done);
  165. });
  166. });
  167. });