I18n.js 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. 'use strict';
  2. var common = require('../common');
  3. describe('I18n', function () {
  4. describe('translate', function () {
  5. this.timeout(30000);
  6. before(function () {
  7. $.PrivateBin.I18n.reset();
  8. });
  9. jsc.property(
  10. 'returns message ID unchanged if no translation found',
  11. 'string',
  12. function (messageId) {
  13. messageId = messageId.replace(/%(s|d)/g, '%%');
  14. var plurals = [messageId, messageId + 's'],
  15. fake = [messageId],
  16. result = $.PrivateBin.I18n.translate(messageId);
  17. $.PrivateBin.I18n.reset();
  18. var alias = $.PrivateBin.I18n._(messageId);
  19. $.PrivateBin.I18n.reset();
  20. var pluralResult = $.PrivateBin.I18n.translate(plurals);
  21. $.PrivateBin.I18n.reset();
  22. var pluralAlias = $.PrivateBin.I18n._(plurals);
  23. $.PrivateBin.I18n.reset();
  24. var fakeResult = $.PrivateBin.I18n.translate(fake);
  25. $.PrivateBin.I18n.reset();
  26. var fakeAlias = $.PrivateBin.I18n._(fake);
  27. $.PrivateBin.I18n.reset();
  28. messageId = $.PrivateBin.Helper.htmlEntities(messageId);
  29. return messageId === result && messageId === alias &&
  30. messageId === pluralResult && messageId === pluralAlias &&
  31. messageId === fakeResult && messageId === fakeAlias;
  32. }
  33. );
  34. jsc.property(
  35. 'replaces %s in strings with first given parameter, encoding all, when no link is in the messageID',
  36. 'string',
  37. '(small nearray) string',
  38. 'string',
  39. function (prefix, params, postfix) {
  40. prefix = prefix.replace(/%(s|d)/g, '%%');
  41. params[0] = params[0].replace(/%(s|d)/g, '%%').replace(/<a/g, '');
  42. postfix = postfix.replace(/%(s|d)/g, '%%');
  43. const translation = $.PrivateBin.Helper.htmlEntities(prefix + params[0] + postfix);
  44. params.unshift(prefix + '%s' + postfix);
  45. const result = $.PrivateBin.I18n.translate.apply(this, params);
  46. $.PrivateBin.I18n.reset();
  47. const alias = $.PrivateBin.I18n._.apply(this, params);
  48. $.PrivateBin.I18n.reset();
  49. return translation === result && translation === alias;
  50. }
  51. );
  52. jsc.property(
  53. 'replaces %s in strings with first given parameter, encoding params only, when a link is part of the messageID',
  54. 'string',
  55. '(small nearray) string',
  56. 'string',
  57. function (prefix, params, postfix) {
  58. prefix = prefix.replace(/%(s|d)/g, '%%');
  59. params[0] = params[0].replace(/%(s|d)/g, '%%');
  60. postfix = postfix.replace(/%(s|d)/g, '%%');
  61. const translation = DOMPurify.sanitize(
  62. prefix + $.PrivateBin.Helper.htmlEntities(params[0]) + '<a></a>' + postfix, {
  63. ALLOWED_TAGS: ['a', 'br', 'i', 'span'],
  64. ALLOWED_ATTR: ['href', 'id']
  65. }
  66. );
  67. params.unshift(prefix + '%s<a></a>' + postfix);
  68. const result = $.PrivateBin.I18n.translate.apply(this, params);
  69. $.PrivateBin.I18n.reset();
  70. const alias = $.PrivateBin.I18n._.apply(this, params);
  71. $.PrivateBin.I18n.reset();
  72. return translation === result && translation === alias;
  73. }
  74. );
  75. jsc.property(
  76. 'replaces %s in strings with first given parameter into an element, encoding all, when no link is in the messageID',
  77. 'string',
  78. '(small nearray) string',
  79. 'string',
  80. function (prefix, params, postfix) {
  81. prefix = prefix.replace(/%(s|d)/g, '%%');
  82. params[0] = params[0].replace(/%(s|d)/g, '%%').replace(/<a/g, '');
  83. postfix = postfix.replace(/%(s|d)/g, '%%');
  84. const translation = $('<textarea>').text((prefix + params[0] + postfix)).text();
  85. let args = Array.prototype.slice.call(params);
  86. args.unshift(prefix + '%s' + postfix);
  87. let clean = jsdom();
  88. $('body').html('<div id="i18n"></div>');
  89. args.unshift($('#i18n'));
  90. $.PrivateBin.I18n.translate.apply(this, args);
  91. const result = $('#i18n').text();
  92. $.PrivateBin.I18n.reset();
  93. clean();
  94. clean = jsdom();
  95. $('body').html('<div id="i18n"></div>');
  96. args[0] = $('#i18n');
  97. $.PrivateBin.I18n._.apply(this, args);
  98. const alias = $('#i18n').text();
  99. $.PrivateBin.I18n.reset();
  100. clean();
  101. return translation === result && translation === alias;
  102. }
  103. );
  104. jsc.property(
  105. 'replaces %s in strings with first given parameter into an element, encoding params only, when a link is part of the messageID inserted',
  106. 'string',
  107. '(small nearray) string',
  108. 'string',
  109. function (prefix, params, postfix) {
  110. prefix = prefix.replace(/%(s|d)/g, '%%').trim();
  111. params[0] = params[0].replace(/%(s|d)/g, '%%').trim();
  112. postfix = postfix.replace(/%(s|d)/g, '%%').trim();
  113. const translation = DOMPurify.sanitize(
  114. prefix + $.PrivateBin.Helper.htmlEntities(params[0]) + '<a></a>' + postfix, {
  115. ALLOWED_TAGS: ['a', 'br', 'i', 'span'],
  116. ALLOWED_ATTR: ['href', 'id']
  117. }
  118. );
  119. let args = Array.prototype.slice.call(params);
  120. args.unshift(prefix + '%s<a></a>' + postfix);
  121. let clean = jsdom();
  122. $('body').html('<div id="i18n"></div>');
  123. args.unshift($('#i18n'));
  124. $.PrivateBin.I18n.translate.apply(this, args);
  125. const result = $('#i18n').html();
  126. $.PrivateBin.I18n.reset();
  127. clean();
  128. clean = jsdom();
  129. $('body').html('<div id="i18n"></div>');
  130. args[0] = $('#i18n');
  131. $.PrivateBin.I18n._.apply(this, args);
  132. const alias = $('#i18n').html();
  133. $.PrivateBin.I18n.reset();
  134. clean();
  135. return translation === result && translation === alias;
  136. }
  137. );
  138. });
  139. describe('getPluralForm', function () {
  140. before(function () {
  141. $.PrivateBin.I18n.reset();
  142. });
  143. jsc.property(
  144. 'returns valid key for plural form',
  145. common.jscSupportedLanguages(),
  146. 'integer',
  147. function(language, n) {
  148. $.PrivateBin.I18n.reset(language);
  149. var result = $.PrivateBin.I18n.getPluralForm(n);
  150. // arabic seems to have the highest plural count with 6 forms
  151. return result >= 0 && result <= 5;
  152. }
  153. );
  154. });
  155. // loading of JSON via AJAX needs to be tested in the browser, this just mocks it
  156. // TODO: This needs to be tested using a browser.
  157. describe('loadTranslations', function () {
  158. this.timeout(30000);
  159. before(function () {
  160. $.PrivateBin.I18n.reset();
  161. });
  162. jsc.property(
  163. 'downloads and handles any supported language',
  164. common.jscSupportedLanguages(),
  165. function(language) {
  166. // cleanup
  167. var clean = jsdom('', {cookie: ['lang=en']});
  168. $.PrivateBin.I18n.reset('en');
  169. $.PrivateBin.I18n.loadTranslations();
  170. clean();
  171. // mock
  172. clean = jsdom('', {cookie: ['lang=' + language]});
  173. $.PrivateBin.I18n.reset(language, require('../../i18n/' + language + '.json'));
  174. var result = $.PrivateBin.I18n.translate('en'),
  175. alias = $.PrivateBin.I18n._('en');
  176. clean();
  177. return language === result && language === alias;
  178. }
  179. );
  180. jsc.property(
  181. 'should default to en',
  182. function() {
  183. var clean = jsdom('', {url: 'https://privatebin.net/'});
  184. // when navigator.userLanguage is undefined and no default language
  185. // is specified, it would throw an error
  186. [ 'language', 'userLanguage' ].forEach(function (key) {
  187. Object.defineProperty(navigator, key, {
  188. value: undefined,
  189. writeable: false
  190. });
  191. });
  192. $.PrivateBin.I18n.reset('en');
  193. $.PrivateBin.I18n.loadTranslations();
  194. var result = $.PrivateBin.I18n.translate('en'),
  195. alias = $.PrivateBin.I18n._('en');
  196. clean();
  197. return 'en' === result && 'en' === alias;
  198. }
  199. );
  200. });
  201. });