@edx/frontend-platform 4.6.2 → 4.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (229) hide show
  1. package/package.json +1 -1
  2. package/.env.development +0 -30
  3. package/.env.test +0 -30
  4. package/.eslintignore +0 -6
  5. package/.eslintrc.js +0 -28
  6. package/.github/PULL_REQUEST_TEMPLATE.md +0 -13
  7. package/.github/workflows/add-depr-ticket-to-depr-board.yml +0 -19
  8. package/.github/workflows/add-remove-label-on-comment.yml +0 -20
  9. package/.github/workflows/ci.yml +0 -42
  10. package/.github/workflows/commitlint.yml +0 -10
  11. package/.github/workflows/lockfileversion-check.yml +0 -13
  12. package/.github/workflows/manual-publish.yml +0 -43
  13. package/.github/workflows/npm-deprecate.yml +0 -22
  14. package/.github/workflows/release.yml +0 -45
  15. package/.github/workflows/self-assign-issue.yml +0 -12
  16. package/.github/workflows/update-browserslist-db.yml +0 -12
  17. package/.nvmrc +0 -1
  18. package/.releaserc +0 -32
  19. package/catalog-info.yaml +0 -21
  20. package/dist/LICENSE +0 -661
  21. package/dist/README.md +0 -155
  22. package/dist/package.json +0 -86
  23. package/docs/addTagsPlugin.js +0 -10
  24. package/docs/auth-API.md +0 -114
  25. package/docs/decisions/0001-record-architecture-decisions.rst +0 -32
  26. package/docs/decisions/0002-frontend-base-design-goals.rst +0 -222
  27. package/docs/decisions/0003-consolidation-into-frontend-platform.rst +0 -71
  28. package/docs/decisions/0004-axios-caching-implementation.rst +0 -88
  29. package/docs/decisions/0005-token-null-after-successful-refresh.rst +0 -69
  30. package/docs/decisions/0006-middleware-support-for-http-clients.rst +0 -44
  31. package/docs/decisions/0007-javascript-file-configuration.rst +0 -143
  32. package/docs/how_tos/automatic-case-conversion.rst +0 -58
  33. package/docs/how_tos/caching.rst +0 -93
  34. package/docs/how_tos/i18n.rst +0 -305
  35. package/docs/removeExport.js +0 -24
  36. package/docs/template/edx/README.md +0 -12
  37. package/docs/template/edx/publish.js +0 -713
  38. package/docs/template/edx/static/fonts/OpenSans-Bold-webfont.eot +0 -0
  39. package/docs/template/edx/static/fonts/OpenSans-Bold-webfont.svg +0 -1830
  40. package/docs/template/edx/static/fonts/OpenSans-Bold-webfont.woff +0 -0
  41. package/docs/template/edx/static/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
  42. package/docs/template/edx/static/fonts/OpenSans-BoldItalic-webfont.svg +0 -1830
  43. package/docs/template/edx/static/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
  44. package/docs/template/edx/static/fonts/OpenSans-Italic-webfont.eot +0 -0
  45. package/docs/template/edx/static/fonts/OpenSans-Italic-webfont.svg +0 -1830
  46. package/docs/template/edx/static/fonts/OpenSans-Italic-webfont.woff +0 -0
  47. package/docs/template/edx/static/fonts/OpenSans-Light-webfont.eot +0 -0
  48. package/docs/template/edx/static/fonts/OpenSans-Light-webfont.svg +0 -1831
  49. package/docs/template/edx/static/fonts/OpenSans-Light-webfont.woff +0 -0
  50. package/docs/template/edx/static/fonts/OpenSans-LightItalic-webfont.eot +0 -0
  51. package/docs/template/edx/static/fonts/OpenSans-LightItalic-webfont.svg +0 -1835
  52. package/docs/template/edx/static/fonts/OpenSans-LightItalic-webfont.woff +0 -0
  53. package/docs/template/edx/static/fonts/OpenSans-Regular-webfont.eot +0 -0
  54. package/docs/template/edx/static/fonts/OpenSans-Regular-webfont.svg +0 -1831
  55. package/docs/template/edx/static/fonts/OpenSans-Regular-webfont.woff +0 -0
  56. package/docs/template/edx/static/scripts/linenumber.js +0 -25
  57. package/docs/template/edx/static/scripts/prettify/Apache-License-2.0.txt +0 -202
  58. package/docs/template/edx/static/scripts/prettify/lang-css.js +0 -2
  59. package/docs/template/edx/static/scripts/prettify/prettify.js +0 -28
  60. package/docs/template/edx/static/styles/jsdoc-default.css +0 -356
  61. package/docs/template/edx/static/styles/prettify-jsdoc.css +0 -111
  62. package/docs/template/edx/static/styles/prettify-tomorrow.css +0 -132
  63. package/docs/template/edx/tmpl/augments.tmpl +0 -10
  64. package/docs/template/edx/tmpl/container.tmpl +0 -196
  65. package/docs/template/edx/tmpl/details.tmpl +0 -143
  66. package/docs/template/edx/tmpl/example.tmpl +0 -2
  67. package/docs/template/edx/tmpl/examples.tmpl +0 -13
  68. package/docs/template/edx/tmpl/exceptions.tmpl +0 -32
  69. package/docs/template/edx/tmpl/layout.tmpl +0 -39
  70. package/docs/template/edx/tmpl/mainpage.tmpl +0 -10
  71. package/docs/template/edx/tmpl/members.tmpl +0 -38
  72. package/docs/template/edx/tmpl/method.tmpl +0 -131
  73. package/docs/template/edx/tmpl/modifies.tmpl +0 -14
  74. package/docs/template/edx/tmpl/params.tmpl +0 -131
  75. package/docs/template/edx/tmpl/properties.tmpl +0 -108
  76. package/docs/template/edx/tmpl/returns.tmpl +0 -19
  77. package/docs/template/edx/tmpl/source.tmpl +0 -8
  78. package/docs/template/edx/tmpl/tutorial.tmpl +0 -19
  79. package/docs/template/edx/tmpl/type.tmpl +0 -7
  80. package/env.config.js +0 -8
  81. package/jsdoc.json +0 -36
  82. package/openedx.yaml +0 -12
  83. package/service-interface.png +0 -0
  84. package/src/analytics/MockAnalyticsService.js +0 -71
  85. package/src/analytics/SegmentAnalyticsService.js +0 -243
  86. package/src/analytics/index.js +0 -12
  87. package/src/analytics/interface.js +0 -142
  88. package/src/auth/AxiosCsrfTokenService.js +0 -60
  89. package/src/auth/AxiosJwtAuthService.js +0 -364
  90. package/src/auth/AxiosJwtTokenService.js +0 -134
  91. package/src/auth/LocalForageCache.js +0 -78
  92. package/src/auth/MockAuthService.js +0 -285
  93. package/src/auth/index.js +0 -19
  94. package/src/auth/interceptors/createCsrfTokenProviderInterceptor.js +0 -37
  95. package/src/auth/interceptors/createJwtTokenProviderInterceptor.js +0 -38
  96. package/src/auth/interceptors/createProcessAxiosRequestErrorInterceptor.js +0 -20
  97. package/src/auth/interceptors/createRetryInterceptor.js +0 -72
  98. package/src/auth/interface.js +0 -309
  99. package/src/auth/utils.js +0 -105
  100. package/src/config.js +0 -327
  101. package/src/constants.js +0 -66
  102. package/src/i18n/countries.js +0 -57
  103. package/src/i18n/index.js +0 -123
  104. package/src/i18n/injectIntlWithShim.jsx +0 -45
  105. package/src/i18n/languages.js +0 -60
  106. package/src/i18n/lib.js +0 -282
  107. package/src/i18n/scripts/README.md +0 -29
  108. package/src/i18n/scripts/intl-imports.js +0 -259
  109. package/src/i18n/scripts/transifex-utils.js +0 -75
  110. package/src/index.js +0 -42
  111. package/src/initialize.js +0 -357
  112. package/src/logging/MockLoggingService.js +0 -31
  113. package/src/logging/NewRelicLoggingService.js +0 -181
  114. package/src/logging/index.js +0 -9
  115. package/src/logging/interface.js +0 -110
  116. package/src/pubSub.js +0 -47
  117. package/src/react/AppContext.jsx +0 -24
  118. package/src/react/AppProvider.jsx +0 -93
  119. package/src/react/AuthenticatedPageRoute.jsx +0 -60
  120. package/src/react/ErrorBoundary.jsx +0 -44
  121. package/src/react/ErrorPage.jsx +0 -76
  122. package/src/react/LoginRedirect.jsx +0 -16
  123. package/src/react/OptionalReduxProvider.jsx +0 -28
  124. package/src/react/PageRoute.jsx +0 -31
  125. package/src/react/hooks.js +0 -50
  126. package/src/react/index.js +0 -16
  127. package/src/scripts/GoogleAnalyticsLoader.js +0 -53
  128. package/src/scripts/index.js +0 -2
  129. package/src/testing/index.js +0 -9
  130. package/src/testing/initializeMockApp.js +0 -77
  131. package/src/testing/mockMessages.js +0 -21
  132. package/src/utils.js +0 -167
  133. /package/{dist/analytics → analytics}/MockAnalyticsService.js +0 -0
  134. /package/{dist/analytics → analytics}/MockAnalyticsService.js.map +0 -0
  135. /package/{dist/analytics → analytics}/SegmentAnalyticsService.js +0 -0
  136. /package/{dist/analytics → analytics}/SegmentAnalyticsService.js.map +0 -0
  137. /package/{dist/analytics → analytics}/index.js +0 -0
  138. /package/{dist/analytics → analytics}/index.js.map +0 -0
  139. /package/{dist/analytics → analytics}/interface.js +0 -0
  140. /package/{dist/analytics → analytics}/interface.js.map +0 -0
  141. /package/{dist/auth → auth}/AxiosCsrfTokenService.js +0 -0
  142. /package/{dist/auth → auth}/AxiosCsrfTokenService.js.map +0 -0
  143. /package/{dist/auth → auth}/AxiosJwtAuthService.js +0 -0
  144. /package/{dist/auth → auth}/AxiosJwtAuthService.js.map +0 -0
  145. /package/{dist/auth → auth}/AxiosJwtTokenService.js +0 -0
  146. /package/{dist/auth → auth}/AxiosJwtTokenService.js.map +0 -0
  147. /package/{dist/auth → auth}/LocalForageCache.js +0 -0
  148. /package/{dist/auth → auth}/LocalForageCache.js.map +0 -0
  149. /package/{dist/auth → auth}/MockAuthService.js +0 -0
  150. /package/{dist/auth → auth}/MockAuthService.js.map +0 -0
  151. /package/{dist/auth → auth}/index.js +0 -0
  152. /package/{dist/auth → auth}/index.js.map +0 -0
  153. /package/{dist/auth → auth}/interceptors/createCsrfTokenProviderInterceptor.js +0 -0
  154. /package/{dist/auth → auth}/interceptors/createCsrfTokenProviderInterceptor.js.map +0 -0
  155. /package/{dist/auth → auth}/interceptors/createJwtTokenProviderInterceptor.js +0 -0
  156. /package/{dist/auth → auth}/interceptors/createJwtTokenProviderInterceptor.js.map +0 -0
  157. /package/{dist/auth → auth}/interceptors/createProcessAxiosRequestErrorInterceptor.js +0 -0
  158. /package/{dist/auth → auth}/interceptors/createProcessAxiosRequestErrorInterceptor.js.map +0 -0
  159. /package/{dist/auth → auth}/interceptors/createRetryInterceptor.js +0 -0
  160. /package/{dist/auth → auth}/interceptors/createRetryInterceptor.js.map +0 -0
  161. /package/{dist/auth → auth}/interface.js +0 -0
  162. /package/{dist/auth → auth}/interface.js.map +0 -0
  163. /package/{dist/auth → auth}/utils.js +0 -0
  164. /package/{dist/auth → auth}/utils.js.map +0 -0
  165. /package/{dist/config.js → config.js} +0 -0
  166. /package/{dist/config.js.map → config.js.map} +0 -0
  167. /package/{dist/constants.js → constants.js} +0 -0
  168. /package/{dist/constants.js.map → constants.js.map} +0 -0
  169. /package/{dist/i18n → i18n}/countries.js +0 -0
  170. /package/{dist/i18n → i18n}/countries.js.map +0 -0
  171. /package/{dist/i18n → i18n}/index.js +0 -0
  172. /package/{dist/i18n → i18n}/index.js.map +0 -0
  173. /package/{dist/i18n → i18n}/injectIntlWithShim.js +0 -0
  174. /package/{dist/i18n → i18n}/injectIntlWithShim.js.map +0 -0
  175. /package/{dist/i18n → i18n}/languages.js +0 -0
  176. /package/{dist/i18n → i18n}/languages.js.map +0 -0
  177. /package/{dist/i18n → i18n}/lib.js +0 -0
  178. /package/{dist/i18n → i18n}/lib.js.map +0 -0
  179. /package/{dist/i18n → i18n}/scripts/README.md +0 -0
  180. /package/{dist/i18n → i18n}/scripts/intl-imports.js +0 -0
  181. /package/{dist/i18n → i18n}/scripts/intl-imports.js.map +0 -0
  182. /package/{dist/i18n → i18n}/scripts/transifex-utils.js +0 -0
  183. /package/{dist/i18n → i18n}/scripts/transifex-utils.js.map +0 -0
  184. /package/{dist/index.js → index.js} +0 -0
  185. /package/{dist/index.js.map → index.js.map} +0 -0
  186. /package/{dist/initialize.js → initialize.js} +0 -0
  187. /package/{dist/initialize.js.map → initialize.js.map} +0 -0
  188. /package/{dist/logging → logging}/MockLoggingService.js +0 -0
  189. /package/{dist/logging → logging}/MockLoggingService.js.map +0 -0
  190. /package/{dist/logging → logging}/NewRelicLoggingService.js +0 -0
  191. /package/{dist/logging → logging}/NewRelicLoggingService.js.map +0 -0
  192. /package/{dist/logging → logging}/index.js +0 -0
  193. /package/{dist/logging → logging}/index.js.map +0 -0
  194. /package/{dist/logging → logging}/interface.js +0 -0
  195. /package/{dist/logging → logging}/interface.js.map +0 -0
  196. /package/{dist/pubSub.js → pubSub.js} +0 -0
  197. /package/{dist/pubSub.js.map → pubSub.js.map} +0 -0
  198. /package/{dist/react → react}/AppContext.js +0 -0
  199. /package/{dist/react → react}/AppContext.js.map +0 -0
  200. /package/{dist/react → react}/AppProvider.js +0 -0
  201. /package/{dist/react → react}/AppProvider.js.map +0 -0
  202. /package/{dist/react → react}/AuthenticatedPageRoute.js +0 -0
  203. /package/{dist/react → react}/AuthenticatedPageRoute.js.map +0 -0
  204. /package/{dist/react → react}/ErrorBoundary.js +0 -0
  205. /package/{dist/react → react}/ErrorBoundary.js.map +0 -0
  206. /package/{dist/react → react}/ErrorPage.js +0 -0
  207. /package/{dist/react → react}/ErrorPage.js.map +0 -0
  208. /package/{dist/react → react}/LoginRedirect.js +0 -0
  209. /package/{dist/react → react}/LoginRedirect.js.map +0 -0
  210. /package/{dist/react → react}/OptionalReduxProvider.js +0 -0
  211. /package/{dist/react → react}/OptionalReduxProvider.js.map +0 -0
  212. /package/{dist/react → react}/PageRoute.js +0 -0
  213. /package/{dist/react → react}/PageRoute.js.map +0 -0
  214. /package/{dist/react → react}/hooks.js +0 -0
  215. /package/{dist/react → react}/hooks.js.map +0 -0
  216. /package/{dist/react → react}/index.js +0 -0
  217. /package/{dist/react → react}/index.js.map +0 -0
  218. /package/{dist/scripts → scripts}/GoogleAnalyticsLoader.js +0 -0
  219. /package/{dist/scripts → scripts}/GoogleAnalyticsLoader.js.map +0 -0
  220. /package/{dist/scripts → scripts}/index.js +0 -0
  221. /package/{dist/scripts → scripts}/index.js.map +0 -0
  222. /package/{dist/testing → testing}/index.js +0 -0
  223. /package/{dist/testing → testing}/index.js.map +0 -0
  224. /package/{dist/testing → testing}/initializeMockApp.js +0 -0
  225. /package/{dist/testing → testing}/initializeMockApp.js.map +0 -0
  226. /package/{dist/testing → testing}/mockMessages.js +0 -0
  227. /package/{dist/testing → testing}/mockMessages.js.map +0 -0
  228. /package/{dist/utils.js → utils.js} +0 -0
  229. /package/{dist/utils.js.map → utils.js.map} +0 -0
package/src/i18n/lib.js DELETED
@@ -1,282 +0,0 @@
1
- import PropTypes from 'prop-types';
2
- import Cookies from 'universal-cookie';
3
- import merge from 'lodash.merge';
4
-
5
- import '@formatjs/intl-pluralrules/polyfill';
6
- import '@formatjs/intl-pluralrules/locale-data/ar';
7
- import '@formatjs/intl-pluralrules/locale-data/en';
8
- import '@formatjs/intl-pluralrules/locale-data/es';
9
- import '@formatjs/intl-pluralrules/locale-data/fr';
10
- import '@formatjs/intl-pluralrules/locale-data/zh';
11
- import '@formatjs/intl-pluralrules/locale-data/ca';
12
- import '@formatjs/intl-pluralrules/locale-data/he';
13
- import '@formatjs/intl-pluralrules/locale-data/id';
14
- import '@formatjs/intl-pluralrules/locale-data/ko';
15
- import '@formatjs/intl-pluralrules/locale-data/pl';
16
- import '@formatjs/intl-pluralrules/locale-data/pt';
17
- import '@formatjs/intl-pluralrules/locale-data/ru';
18
- import '@formatjs/intl-pluralrules/locale-data/th';
19
- import '@formatjs/intl-pluralrules/locale-data/uk';
20
-
21
- import '@formatjs/intl-relativetimeformat/polyfill';
22
- import '@formatjs/intl-relativetimeformat/locale-data/ar';
23
- import '@formatjs/intl-relativetimeformat/locale-data/en';
24
- import '@formatjs/intl-relativetimeformat/locale-data/es';
25
- import '@formatjs/intl-relativetimeformat/locale-data/fr';
26
- import '@formatjs/intl-relativetimeformat/locale-data/zh';
27
- import '@formatjs/intl-relativetimeformat/locale-data/ca';
28
- import '@formatjs/intl-relativetimeformat/locale-data/he';
29
- import '@formatjs/intl-relativetimeformat/locale-data/id';
30
- import '@formatjs/intl-relativetimeformat/locale-data/ko';
31
- import '@formatjs/intl-relativetimeformat/locale-data/pl';
32
- import '@formatjs/intl-relativetimeformat/locale-data/pt';
33
- import '@formatjs/intl-relativetimeformat/locale-data/ru';
34
- import '@formatjs/intl-relativetimeformat/locale-data/th';
35
- import '@formatjs/intl-relativetimeformat/locale-data/uk';
36
-
37
- const cookies = new Cookies();
38
- const supportedLocales = [
39
- 'ar', // Arabic
40
- // NOTE: 'en' is not included in this list intentionally, since it's the fallback.
41
- 'es-419', // Spanish, Latin American
42
- 'fa', // Farsi
43
- 'fa-ir', // Farsi, Iran
44
- 'fr', // French
45
- 'zh-cn', // Chinese, Simplified
46
- 'ca', // Catalan
47
- 'he', // Hebrew
48
- 'id', // Indonesian
49
- 'ko-kr', // Korean (Korea)
50
- 'pl', // Polish
51
- 'pt-br', // Portuguese (Brazil)
52
- 'ru', // Russian
53
- 'th', // Thai
54
- 'uk', // Ukrainian
55
- ];
56
- const rtlLocales = [
57
- 'ar', // Arabic
58
- 'he', // Hebrew
59
- 'fa', // Farsi (not currently supported)
60
- 'fa-ir', // Farsi Iran
61
- 'ur', // Urdu (not currently supported)
62
- ];
63
-
64
- let config = null;
65
- let loggingService = null;
66
- let messages = null;
67
-
68
- /**
69
- * @memberof module:Internationalization
70
- *
71
- * Prior versions of react-intl (our primary implementation of the i18n service) included a
72
- * PropTypes-based 'shape' for its `intl` object. This has since been removed. For legacy
73
- * compatibility, we include an `intlShape` export that is set to PropTypes.object. Usage of this
74
- * export is deprecated.
75
- *
76
- * @deprecated
77
- */
78
- export const intlShape = PropTypes.object;
79
-
80
- /**
81
- *
82
- * @ignore
83
- * @returns {LoggingService}
84
- */
85
- export const getLoggingService = () => loggingService;
86
-
87
- /**
88
- * @memberof module:Internationalization
89
- */
90
- export const LOCALE_TOPIC = 'LOCALE';
91
-
92
- /**
93
- * @memberof module:Internationalization
94
- */
95
- export const LOCALE_CHANGED = `${LOCALE_TOPIC}.CHANGED`;
96
-
97
- /**
98
- *
99
- * @memberof module:Internationalization
100
- * @returns {Cookies}
101
- */
102
- export function getCookies() {
103
- return cookies;
104
- }
105
-
106
- /**
107
- * Some of our dependencies function on primary language subtags, rather than full locales.
108
- * This function strips a locale down to that first subtag. Depending on the code, this
109
- * may be 2 or more characters.
110
- *
111
- * @param {string} code
112
- * @memberof module:Internationalization
113
- */
114
- export function getPrimaryLanguageSubtag(code) {
115
- return code.split('-')[0];
116
- }
117
-
118
- /**
119
- * Finds the closest supported locale to the one provided. This is done in three steps:
120
- *
121
- * 1. Returning the locale itself if its exact language code is supported.
122
- * 2. Returning the primary language subtag of the language code if it is supported (ar for ar-eg,
123
- * for instance).
124
- * 3. Returning 'en' if neither of the above produce a supported locale.
125
- *
126
- * @param {string} locale
127
- * @returns {string}
128
- * @memberof module:Internationalization
129
- */
130
- export function findSupportedLocale(locale) {
131
- if (messages[locale] !== undefined) {
132
- return locale;
133
- }
134
-
135
- if (messages[getPrimaryLanguageSubtag(locale)] !== undefined) {
136
- return getPrimaryLanguageSubtag(locale);
137
- }
138
-
139
- return 'en';
140
- }
141
-
142
- /**
143
- * Get the locale from the cookie or, failing that, the browser setting.
144
- * Gracefully fall back to a more general primary language subtag or to English (en)
145
- * if we don't support that language.
146
- *
147
- * @param {string} locale If a locale is provided, returns the closest supported locale. Optional.
148
- * @throws An error if i18n has not yet been configured.
149
- * @returns {string}
150
- * @memberof module:Internationalization
151
- */
152
- export function getLocale(locale) {
153
- if (messages === null) {
154
- throw new Error('getLocale called before configuring i18n. Call configure with messages first.');
155
- }
156
- // 1. Explicit application request
157
- if (locale !== undefined) {
158
- return findSupportedLocale(locale);
159
- }
160
- // 2. User setting in cookie
161
- const cookieLangPref = cookies
162
- .get(config.LANGUAGE_PREFERENCE_COOKIE_NAME);
163
- if (cookieLangPref) {
164
- return findSupportedLocale(cookieLangPref.toLowerCase());
165
- }
166
- // 3. Browser language (default)
167
- // Note that some browers prefer upper case for the region part of the locale, while others don't.
168
- // Thus the toLowerCase, for consistency.
169
- // https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/language
170
- return findSupportedLocale(global.navigator.language.toLowerCase());
171
- }
172
-
173
- /**
174
- * Returns messages for the provided locale, or the user's preferred locale if no argument is
175
- * provided.
176
- *
177
- * @param {string} [locale=getLocale()]
178
- * @memberof module:Internationalization
179
- */
180
- export function getMessages(locale = getLocale()) {
181
- return messages[locale];
182
- }
183
-
184
- /**
185
- * Determines if the provided locale is a right-to-left language.
186
- *
187
- * @param {string} locale
188
- * @memberof module:Internationalization
189
- */
190
- export function isRtl(locale) {
191
- return rtlLocales.includes(locale);
192
- }
193
-
194
- /**
195
- * Handles applying the RTL stylesheet and "dir=rtl" attribute to the html tag if the current locale
196
- * is a RTL language.
197
- *
198
- * @memberof module:Internationalization
199
- */
200
- export function handleRtl() {
201
- if (isRtl(getLocale())) {
202
- global.document.getElementsByTagName('html')[0].setAttribute('dir', 'rtl');
203
- } else {
204
- global.document.getElementsByTagName('html')[0].setAttribute('dir', 'ltr');
205
- }
206
- }
207
-
208
- const messagesShape = {
209
- ar: PropTypes.objectOf(PropTypes.string), // Arabic
210
- en: PropTypes.objectOf(PropTypes.string),
211
- 'es-419': PropTypes.objectOf(PropTypes.string), // Spanish, Latin American
212
- fr: PropTypes.objectOf(PropTypes.string), // French
213
- 'zh-cn': PropTypes.objectOf(PropTypes.string), // Chinese, Simplified
214
- ca: PropTypes.objectOf(PropTypes.string), // Catalan
215
- he: PropTypes.objectOf(PropTypes.string), // Hebrew
216
- id: PropTypes.objectOf(PropTypes.string), // Indonesian
217
- 'ko-kr': PropTypes.objectOf(PropTypes.string), // Korean (Korea)
218
- pl: PropTypes.objectOf(PropTypes.string), // Polish
219
- 'pt-br': PropTypes.objectOf(PropTypes.string), // Portuguese (Brazil)
220
- ru: PropTypes.objectOf(PropTypes.string), // Russian
221
- th: PropTypes.objectOf(PropTypes.string), // Thai
222
- uk: PropTypes.objectOf(PropTypes.string), // Ukrainian
223
- };
224
-
225
- const optionsShape = {
226
- config: PropTypes.object.isRequired,
227
- loggingService: PropTypes.shape({
228
- logError: PropTypes.func.isRequired,
229
- }).isRequired,
230
- messages: PropTypes.oneOfType([
231
- PropTypes.shape(messagesShape),
232
- PropTypes.arrayOf(PropTypes.shape(messagesShape)),
233
- ]).isRequired,
234
- };
235
-
236
- /**
237
- *
238
- *
239
- * @param {Array} [messagesArray=[]]
240
- * @returns {Object}
241
- * @memberof module:Internationalization
242
- */
243
- export function mergeMessages(messagesArray = []) {
244
- return Array.isArray(messagesArray) ? merge({}, ...messagesArray) : {};
245
- }
246
-
247
- /**
248
- * Configures the i18n library with messages for your application.
249
- *
250
- * Logs a warning if it detects a locale it doesn't expect (as defined by the supportedLocales list
251
- * above), or if an expected locale is not provided.
252
- *
253
- * @param {Object} options
254
- * @param {LoggingService} options.loggingService
255
- * @param {Object} options.config
256
- * @param {Object} options.messages
257
- * @memberof module:Internationalization
258
- */
259
- export function configure(options) {
260
- PropTypes.checkPropTypes(optionsShape, options, 'property', 'i18n');
261
- // eslint-disable-next-line prefer-destructuring
262
- loggingService = options.loggingService;
263
- // eslint-disable-next-line prefer-destructuring
264
- config = options.config;
265
- messages = Array.isArray(options.messages) ? mergeMessages(options.messages) : options.messages;
266
-
267
- if (config.ENVIRONMENT !== 'production') {
268
- Object.keys(messages).forEach((key) => {
269
- if (supportedLocales.indexOf(key) < 0) {
270
- console.warn(`Unexpected locale: ${key}`); // eslint-disable-line no-console
271
- }
272
- });
273
-
274
- supportedLocales.forEach((key) => {
275
- if (messages[key] === undefined) {
276
- console.warn(`Missing locale: ${key}`); // eslint-disable-line no-console
277
- }
278
- });
279
- }
280
-
281
- handleRtl();
282
- }
@@ -1,29 +0,0 @@
1
- # i18n/scripts
2
-
3
- This directory contains the `transifex-utils.js` and `intl-imports.js` files which are shared across all micro-frontends.
4
-
5
- The package.json of `frontend-platform` includes the following sections:
6
-
7
- ```
8
- "bin": {
9
- "intl-imports.js": "i18n/scripts/intl-imports.js"
10
- "transifex-utils.js": "i18n/scripts/transifex-utils.js"
11
- },
12
- ```
13
-
14
- This config block causes boths scripts to be copied to the following path when `frontend-platform` is installed as a
15
- dependency of a micro-frontend:
16
-
17
- ```
18
- /node_modules/.bin/intl-imports.js
19
- /node_modules/.bin/transifex-utils.js
20
- ```
21
-
22
- All micro-frontends have a `Makefile` with a line that loads the scripts from the above path:
23
-
24
- ```
25
- intl_imports = ./node_modules/.bin/intl-imports.js
26
- transifex_utils = ./node_modules/.bin/transifex-utils.js
27
- ```
28
-
29
- So if you delete either of the files or the `scripts` directory, you'll break all micro-frontend builds. Happy coding!
@@ -1,259 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- const scriptHelpDocument = `
4
- NAME
5
- intl-imports.js — Script to generate the src/i18n/index.js file that exports messages from all the languages for Micro-frontends.
6
-
7
- SYNOPSIS
8
- intl-imports.js [DIRECTORY ...]
9
-
10
- DESCRIPTION
11
- This script is intended to run after 'atlas' has pulled the files.
12
-
13
- This expects to run inside a Micro-frontend root directory with the following structure:
14
-
15
- frontend-app-learning $ tree src/i18n/
16
- src/i18n/
17
- ├── index.js
18
- └── messages
19
- ├── frontend-app-example
20
- │ ├── ar.json
21
- │ ├── es_419.json
22
- │ └── zh_CN.json
23
- ├── frontend-component-footer
24
- │ ├── ar.json
25
- │ ├── es_419.json
26
- │ └── zh_CN.json
27
- └── frontend-component-header (empty directory)
28
-
29
-
30
-
31
- With the structure above it's expected to run with the following command in Makefile:
32
-
33
-
34
- $ node_modules/.bin/intl-imports.js frontend-component-footer frontend-component-header frontend-app-example
35
-
36
-
37
- It will generate two type of files:
38
-
39
- - Main src/i18n/index.js which overrides the Micro-frontend provided with a sample output of:
40
-
41
- """
42
- import messagesFromFrontendComponentFooter from './messages/frontend-component-footer';
43
- // Skipped import due to missing './messages/frontend-component-footer/index.js' likely due to empty translations.
44
- import messagesFromFrontendAppExample from './messages/frontend-app-example';
45
-
46
- export default [
47
- messagesFromFrontendComponentFooter,
48
- messagesFromFrontendAppExample,
49
- ];
50
- """
51
-
52
- - Each sub-directory has src/i18n/messages/frontend-component-header/index.js which is imported by the main file.:
53
-
54
- """
55
- import messagesOfArLanguage from './ar.json';
56
- import messagesOfDeLanguage from './de.json';
57
- import messagesOfEs419Language from './es_419.json';
58
- export default {
59
- 'ar': messagesOfArLanguage,
60
- 'de': messagesOfDeLanguage,
61
- 'es-419': messagesOfEs419Language,
62
- };
63
- """
64
- `;
65
-
66
- const fs = require('fs');
67
- const path = require('path');
68
- const camelCase = require('lodash.camelcase');
69
-
70
- const loggingPrefix = path.basename(`${__filename}`); // the name of this JS file
71
-
72
- // Header note for generated src/i18n/index.js file
73
- const filesCodeGeneratorNoticeHeader = `// This file is generated by the openedx/frontend-platform's "intl-import.js" script.
74
- //
75
- // Refer to the i18n documents in https://docs.openedx.org/en/latest/developers/references/i18n.html to update
76
- // the file and use the Micro-frontend i18n pattern in new repositories.
77
- //
78
- `;
79
-
80
- /**
81
- * Create frontend-app-example/index.js file with proper imports.
82
- *
83
- * @param directory - a directory name containing .json files from Transifex e.g. "frontend-app-example".
84
- * @param log - Mockable process.stdout.write
85
- * @param writeFileSync - Mockable fs.writeFileSync
86
- * @param i18nDir - Path to `src/i18n` directory
87
- *
88
- * @return object - An object containing directory name and whether its "index.js" file was successfully written.
89
- */
90
- function generateSubdirectoryMessageFile({
91
- directory,
92
- log,
93
- writeFileSync,
94
- i18nDir,
95
- }) {
96
- const importLines = [];
97
- const messagesLines = [];
98
- const counter = { nonEmptyLanguages: 0 };
99
- const messagesDir = `${i18nDir}/messages`; // The directory of Micro-frontend i18n messages
100
-
101
- try {
102
- const files = fs.readdirSync(`${messagesDir}/${directory}`, { withFileTypes: true });
103
- files.sort(); // Sorting ensures a consistent generated `index.js` order of imports cross-platforms.
104
-
105
- const jsonFiles = files.filter(file => file.isFile() && file.name.endsWith('.json'));
106
-
107
- if (!jsonFiles.length) {
108
- log(`${loggingPrefix}: Not creating '${directory}/index.js' because no .json translation files were found.\n`);
109
- return {
110
- directory,
111
- isWritten: false,
112
- };
113
- }
114
-
115
- jsonFiles.forEach((file) => {
116
- const filename = file.name;
117
- // Gets `fr_CA` from `fr_CA.json`
118
- const languageCode = filename.replace(/\.json$/, '');
119
- // React-friendly language code fr_CA --> fr-ca
120
- const reactIntlLanguageCode = languageCode.toLowerCase().replace(/_/g, '-');
121
- // camelCase variable name
122
- const messagesCamelCaseVar = camelCase(`messages_Of_${languageCode}_Language`);
123
- const filePath = `${messagesDir}/${directory}/${filename}`;
124
-
125
- try {
126
- const entries = JSON.parse(fs.readFileSync(filePath, { encoding: 'utf8' }));
127
-
128
- if (!Object.keys(entries).length) {
129
- importLines.push(`// Note: Skipped empty '${filename}' messages file.`);
130
- return; // Skip the language
131
- }
132
- } catch (e) {
133
- importLines.push(`// Error: unable to parse '${filename}' messages file.`);
134
- log(`${loggingPrefix}: NOTICE: Skipping '${directory}/${filename}' due to error: ${e}.\n`);
135
- return; // Skip the language
136
- }
137
-
138
- counter.nonEmptyLanguages += 1;
139
- importLines.push(`import ${messagesCamelCaseVar} from './${filename}';`);
140
- messagesLines.splice(1, 0, ` '${reactIntlLanguageCode}': ${messagesCamelCaseVar},`);
141
- });
142
-
143
- if (counter.nonEmptyLanguages) {
144
- // See the help message above for sample output.
145
- const messagesFileContent = [
146
- filesCodeGeneratorNoticeHeader,
147
- importLines.join('\n'),
148
- '\nexport default {',
149
- messagesLines.join('\n'),
150
- '};\n',
151
- ].join('\n');
152
-
153
- writeFileSync(`${messagesDir}/${directory}/index.js`, messagesFileContent);
154
- return {
155
- directory,
156
- isWritten: true,
157
- };
158
- }
159
- log(`${loggingPrefix}: Skipping '${directory}' because no languages were found.\n`);
160
- } catch (e) {
161
- log(`${loggingPrefix}: NOTICE: Skipping '${directory}' due to error: ${e}.\n`);
162
- }
163
-
164
- return {
165
- directory,
166
- isWritten: false,
167
- };
168
- }
169
-
170
- /**
171
- * Create main `src/i18n/index.js` messages import file.
172
- *
173
- *
174
- * @param processedDirectories - List of directories with a boolean flag whether its "index.js" file is written
175
- * The format is "[\{ directory: "frontend-component-example", isWritten: false \}, ...]"
176
- * @param log - Mockable process.stdout.write
177
- * @param writeFileSync - Mockable fs.writeFileSync
178
- * @param i18nDir` - Path to `src/i18n` directory
179
- */
180
- function generateMainMessagesFile({
181
- processedDirectories,
182
- log,
183
- writeFileSync,
184
- i18nDir,
185
- }) {
186
- const importLines = [];
187
- const exportLines = [];
188
-
189
- processedDirectories.forEach(processedDirectory => {
190
- const { directory, isWritten } = processedDirectory;
191
- if (isWritten) {
192
- const moduleCamelCaseVariableName = camelCase(`messages_from_${directory}`);
193
- importLines.push(`import ${moduleCamelCaseVariableName} from './messages/${directory}';`);
194
- exportLines.push(` ${moduleCamelCaseVariableName},`);
195
- } else {
196
- const skipMessage = `Skipped import due to missing '${directory}/index.js' likely due to empty translations.`;
197
- importLines.push(`// ${skipMessage}.`);
198
- log(`${loggingPrefix}: ${skipMessage}\n`);
199
- }
200
- });
201
-
202
- // See the help message above for sample output.
203
- const indexFileContent = [
204
- filesCodeGeneratorNoticeHeader,
205
- importLines.join('\n'),
206
- '\nexport default [',
207
- exportLines.join('\n'),
208
- '];\n',
209
- ].join('\n');
210
-
211
- writeFileSync(`${i18nDir}/index.js`, indexFileContent);
212
- }
213
-
214
- /*
215
- * Main function of the file.
216
- */
217
- function main({
218
- directories,
219
- log,
220
- writeFileSync,
221
- pwd,
222
- }) {
223
- const i18nDir = `${pwd}/src/i18n`; // The Micro-frontend i18n root directory
224
-
225
- if (directories.includes('--help') || directories.includes('-h')) {
226
- log(scriptHelpDocument);
227
- } else if (!directories.length) {
228
- log(scriptHelpDocument);
229
- log(`${loggingPrefix}: Error: A list of directories is required.\n`);
230
- } else if (!fs.existsSync(i18nDir) || !fs.lstatSync(i18nDir).isDirectory()) {
231
- log(scriptHelpDocument);
232
- log(`${loggingPrefix}: Error: src/i18n directory was not found.\n`);
233
- } else {
234
- const processedDirectories = directories.map(directory => generateSubdirectoryMessageFile({
235
- directory,
236
- log,
237
- writeFileSync,
238
- i18nDir,
239
- }));
240
- generateMainMessagesFile({
241
- processedDirectories,
242
- log,
243
- writeFileSync,
244
- i18nDir,
245
- });
246
- }
247
- }
248
-
249
- if (require.main === module) {
250
- // Run the main() function if called from the command line.
251
- main({
252
- directories: process.argv.slice(2),
253
- log: text => process.stdout.write(text),
254
- writeFileSync: fs.writeFileSync,
255
- pwd: process.env.PWD,
256
- });
257
- }
258
-
259
- module.exports.main = main; // Allow tests to use the main function.
@@ -1,75 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- const fs = require('fs');
4
- const glob = require('glob');
5
- const path = require('path');
6
-
7
- /*
8
- * See the Makefile for how the required hash file is downloaded from Transifex.
9
- */
10
-
11
- /*
12
- * Expected input: a directory, possibly containing subdirectories, with .json files. Each .json
13
- * file is an array of translation triplets (id, description, defaultMessage).
14
- *
15
- *
16
- */
17
- function gatherJson(dir) {
18
- const ret = [];
19
- const files = glob.sync(`${dir}/**/*.json`);
20
-
21
- files.forEach((filename) => {
22
- const messages = JSON.parse(fs.readFileSync(filename));
23
- ret.push(...messages);
24
- });
25
- return ret;
26
- }
27
-
28
- // the hash file returns ids whose periods are "escaped" (sort of), like this:
29
- // "key": "profile\\.sociallinks\\.social\\.links"
30
- // so our regular messageIds won't match them out of the box
31
- function escapeDots(messageId) {
32
- return messageId.replace(/\./g, '\\.');
33
- }
34
-
35
- const jsonDir = process.argv[2];
36
- const messageObjects = gatherJson(jsonDir);
37
-
38
- if (messageObjects.length === 0) {
39
- process.exitCode = 1;
40
- throw new Error('Found no messages');
41
- }
42
-
43
- if (process.argv[3] === '--comments') { // prepare to handle the translator notes
44
- const loggingPrefix = path.basename(`${__filename}`); // the name of this JS file
45
- const bashScriptsPath = (
46
- process.argv[4] && process.argv[4] === '--v3-scripts-path'
47
- ? './node_modules/@edx/reactifex/bash_scripts'
48
- : './node_modules/reactifex/bash_scripts');
49
-
50
- const hashFile = `${bashScriptsPath}/hashmap.json`;
51
- process.stdout.write(`${loggingPrefix}: reading hash file ${hashFile}\n`);
52
- const messageInfo = JSON.parse(fs.readFileSync(hashFile));
53
-
54
- const outputFile = `${bashScriptsPath}/hashed_data.txt`;
55
- process.stdout.write(`${loggingPrefix}: writing to output file ${outputFile}\n`);
56
- fs.writeFileSync(outputFile, '');
57
-
58
- messageObjects.forEach((message) => {
59
- const transifexFormatId = escapeDots(message.id);
60
-
61
- const info = messageInfo.find(mi => mi.key === transifexFormatId);
62
- if (info) {
63
- fs.appendFileSync(outputFile, `${info.string_hash}|${message.description}\n`);
64
- } else {
65
- process.stdout.write(`${loggingPrefix}: string ${message.id} does not yet exist on transifex!\n`);
66
- }
67
- });
68
- } else {
69
- const output = {};
70
-
71
- messageObjects.forEach((message) => {
72
- output[message.id] = message.defaultMessage;
73
- });
74
- fs.writeFileSync(process.argv[3], JSON.stringify(output, null, 2));
75
- }
package/src/index.js DELETED
@@ -1,42 +0,0 @@
1
- export {
2
- modifyObjectKeys,
3
- camelCaseObject,
4
- snakeCaseObject,
5
- convertKeyNames,
6
- getQueryParameters,
7
- ensureDefinedConfig,
8
- } from './utils';
9
- export {
10
- APP_TOPIC,
11
- APP_PUBSUB_INITIALIZED,
12
- APP_CONFIG_INITIALIZED,
13
- APP_AUTH_INITIALIZED,
14
- APP_I18N_INITIALIZED,
15
- APP_LOGGING_INITIALIZED,
16
- APP_ANALYTICS_INITIALIZED,
17
- APP_READY,
18
- APP_INIT_ERROR,
19
- CONFIG_TOPIC,
20
- CONFIG_CHANGED,
21
- } from './constants';
22
- export {
23
- initialize,
24
- history,
25
- initError,
26
- auth,
27
- } from './initialize';
28
- export {
29
- publish,
30
- subscribe,
31
- unsubscribe,
32
- } from './pubSub';
33
- export {
34
- getConfig,
35
- setConfig,
36
- mergeConfig,
37
- ensureConfig,
38
- } from './config';
39
- export {
40
- initializeMockApp,
41
- mockMessages,
42
- } from './testing';