i18n.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. // Converse.js (A browser based XMPP chat client)
  2. // http://conversejs.org
  3. //
  4. // This is the internationalization module.
  5. //
  6. // Copyright (c) 2013-2017, Jan-Carel Brand <jc@opkode.com>
  7. // Licensed under the Mozilla Public License (MPLv2)
  8. //
  9. /*global define */
  10. (function (root, factory) {
  11. define([
  12. "es6-promise",
  13. "jed",
  14. "lodash.noconflict",
  15. "moment",
  16. 'moment/locale/af',
  17. 'moment/locale/ar',
  18. 'moment/locale/bg',
  19. 'moment/locale/ca',
  20. 'moment/locale/cs',
  21. 'moment/locale/de',
  22. 'moment/locale/es',
  23. 'moment/locale/eu',
  24. 'moment/locale/fr',
  25. 'moment/locale/he',
  26. 'moment/locale/hi',
  27. 'moment/locale/hu',
  28. 'moment/locale/id',
  29. 'moment/locale/it',
  30. 'moment/locale/ja',
  31. 'moment/locale/nb',
  32. 'moment/locale/nl',
  33. 'moment/locale/pl',
  34. 'moment/locale/pt-br',
  35. 'moment/locale/ro',
  36. 'moment/locale/ru',
  37. 'moment/locale/tr',
  38. 'moment/locale/uk',
  39. 'moment/locale/zh-cn',
  40. 'moment/locale/zh-tw'
  41. ], factory);
  42. }(this, function (Promise, Jed, _, moment) {
  43. 'use strict';
  44. function detectLocale (library_check) {
  45. /* Determine which locale is supported by the user's system as well
  46. * as by the relevant library (e.g. converse.js or moment.js).
  47. *
  48. * Parameters:
  49. * (Function) library_check - Returns a boolean indicating whether
  50. * the locale is supported.
  51. */
  52. var locale, i;
  53. if (window.navigator.userLanguage) {
  54. locale = isLocaleAvailable(window.navigator.userLanguage, library_check);
  55. }
  56. if (window.navigator.languages && !locale) {
  57. for (i=0; i<window.navigator.languages.length && !locale; i++) {
  58. locale = isLocaleAvailable(window.navigator.languages[i], library_check);
  59. }
  60. }
  61. if (window.navigator.browserLanguage && !locale) {
  62. locale = isLocaleAvailable(window.navigator.browserLanguage, library_check);
  63. }
  64. if (window.navigator.language && !locale) {
  65. locale = isLocaleAvailable(window.navigator.language, library_check);
  66. }
  67. if (window.navigator.systemLanguage && !locale) {
  68. locale = isLocaleAvailable(window.navigator.systemLanguage, library_check);
  69. }
  70. return locale || 'en';
  71. }
  72. function isMomentLocale (locale) {
  73. return _.includes(moment.locales(), locale);
  74. }
  75. function isConverseLocale (locale, supported_locales) {
  76. return _.isString(locale) && _.includes(supported_locales, locale);
  77. }
  78. function getLocale (preferred_locale, isSupportedByLibrary) {
  79. if (_.isString(preferred_locale)) {
  80. if (preferred_locale === 'en' || isSupportedByLibrary(preferred_locale)) {
  81. return preferred_locale;
  82. }
  83. }
  84. return detectLocale(isSupportedByLibrary) || 'en';
  85. }
  86. function isLocaleAvailable (locale, available) {
  87. /* Check whether the locale or sub locale (e.g. en-US, en) is supported.
  88. *
  89. * Parameters:
  90. * (String) locale - The locale to check for
  91. * (Function) available - returns a boolean indicating whether the locale is supported
  92. */
  93. if (available(locale)) {
  94. return locale;
  95. } else {
  96. var sublocale = locale.split("-")[0];
  97. if (sublocale !== locale && available(sublocale)) {
  98. return sublocale;
  99. }
  100. }
  101. }
  102. let jed_instance;
  103. return {
  104. setLocales (preferred_locale, _converse) {
  105. _converse.locale = getLocale(
  106. preferred_locale,
  107. _.partial(isConverseLocale, _, _converse.locales)
  108. );
  109. moment.locale(getLocale(preferred_locale, isMomentLocale));
  110. },
  111. translate (str) {
  112. if (_.isNil(jed_instance)) {
  113. return Jed.sprintf.apply(Jed, arguments);
  114. }
  115. var t = jed_instance.translate(str);
  116. if (arguments.length>1) {
  117. return t.fetch.apply(t, [].slice.call(arguments, 1));
  118. } else {
  119. return t.fetch();
  120. }
  121. },
  122. fetchTranslations (locale, supported_locales, locale_url) {
  123. /* Fetch the translations for the given local at the given URL.
  124. *
  125. * Parameters:
  126. * (String) locale: The given i18n locale
  127. * (Array) supported_locales: List of locales supported
  128. * (String) locale_url: The URL from which the translations
  129. * should be fetched.
  130. */
  131. return new Promise((resolve, reject) => {
  132. if (!isConverseLocale(locale, supported_locales) || locale === 'en') {
  133. return resolve();
  134. }
  135. const xhr = new XMLHttpRequest();
  136. xhr.open('GET', locale_url, true);
  137. xhr.setRequestHeader(
  138. 'Accept',
  139. "application/json, text/javascript"
  140. );
  141. xhr.onload = function () {
  142. if (xhr.status >= 200 && xhr.status < 400) {
  143. try {
  144. const data = window.JSON.parse(xhr.responseText);
  145. jed_instance = new Jed(data);
  146. resolve();
  147. } catch (e) {
  148. xhr.onerror(e);
  149. }
  150. } else {
  151. xhr.onerror();
  152. }
  153. };
  154. xhr.onerror = (e) => {
  155. const err_message = e ? ` Error: ${e.message}` : '';
  156. reject(new Error(`Could not fetch translations. Status: ${xhr.statusText}. ${err_message}`));
  157. }
  158. xhr.send();
  159. });
  160. }
  161. };
  162. }));