react-intl 2.3.0 → 2.4.0

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 (263) hide show
  1. package/dist/react-intl.js +960 -948
  2. package/dist/react-intl.js.map +1 -1
  3. package/dist/react-intl.min.js +1 -2
  4. package/dist/react-intl.min.js.map +1 -1
  5. package/lib/index.es.js +971 -970
  6. package/lib/index.js +971 -970
  7. package/locale-data/af.js +1 -1
  8. package/locale-data/agq.js +1 -1
  9. package/locale-data/ak.js +1 -1
  10. package/locale-data/am.js +1 -1
  11. package/locale-data/ar.js +1 -1
  12. package/locale-data/ars.js +1 -0
  13. package/locale-data/as.js +1 -1
  14. package/locale-data/asa.js +1 -1
  15. package/locale-data/ast.js +1 -1
  16. package/locale-data/az.js +1 -1
  17. package/locale-data/bas.js +1 -1
  18. package/locale-data/be.js +1 -1
  19. package/locale-data/bem.js +1 -1
  20. package/locale-data/bez.js +1 -1
  21. package/locale-data/bg.js +1 -1
  22. package/locale-data/bh.js +1 -1
  23. package/locale-data/bm.js +1 -1
  24. package/locale-data/bn.js +1 -1
  25. package/locale-data/bo.js +1 -1
  26. package/locale-data/br.js +1 -1
  27. package/locale-data/brx.js +1 -1
  28. package/locale-data/bs.js +1 -1
  29. package/locale-data/ca.js +1 -1
  30. package/locale-data/ce.js +1 -1
  31. package/locale-data/cgg.js +1 -1
  32. package/locale-data/chr.js +1 -1
  33. package/locale-data/ckb.js +1 -1
  34. package/locale-data/cs.js +1 -1
  35. package/locale-data/cu.js +1 -1
  36. package/locale-data/cy.js +1 -1
  37. package/locale-data/da.js +1 -1
  38. package/locale-data/dav.js +1 -1
  39. package/locale-data/de.js +1 -1
  40. package/locale-data/dje.js +1 -1
  41. package/locale-data/dsb.js +1 -1
  42. package/locale-data/dua.js +1 -1
  43. package/locale-data/dv.js +1 -1
  44. package/locale-data/dyo.js +1 -1
  45. package/locale-data/dz.js +1 -1
  46. package/locale-data/ebu.js +1 -1
  47. package/locale-data/ee.js +1 -1
  48. package/locale-data/el.js +1 -1
  49. package/locale-data/en.js +1 -1
  50. package/locale-data/eo.js +1 -1
  51. package/locale-data/es.js +1 -1
  52. package/locale-data/et.js +1 -1
  53. package/locale-data/eu.js +1 -1
  54. package/locale-data/ewo.js +1 -1
  55. package/locale-data/fa.js +1 -1
  56. package/locale-data/ff.js +1 -1
  57. package/locale-data/fi.js +1 -1
  58. package/locale-data/fil.js +1 -1
  59. package/locale-data/fo.js +1 -1
  60. package/locale-data/fr.js +1 -1
  61. package/locale-data/fur.js +1 -1
  62. package/locale-data/fy.js +1 -1
  63. package/locale-data/ga.js +1 -1
  64. package/locale-data/gd.js +1 -1
  65. package/locale-data/gl.js +1 -1
  66. package/locale-data/gsw.js +1 -1
  67. package/locale-data/gu.js +1 -1
  68. package/locale-data/guw.js +1 -1
  69. package/locale-data/guz.js +1 -1
  70. package/locale-data/gv.js +1 -1
  71. package/locale-data/ha.js +1 -1
  72. package/locale-data/haw.js +1 -1
  73. package/locale-data/he.js +1 -1
  74. package/locale-data/hi.js +1 -1
  75. package/locale-data/hr.js +1 -1
  76. package/locale-data/hsb.js +1 -1
  77. package/locale-data/hu.js +1 -1
  78. package/locale-data/hy.js +1 -1
  79. package/locale-data/id.js +1 -1
  80. package/locale-data/ig.js +1 -1
  81. package/locale-data/ii.js +1 -1
  82. package/locale-data/in.js +1 -1
  83. package/locale-data/index.js +1 -10
  84. package/locale-data/is.js +1 -1
  85. package/locale-data/it.js +1 -1
  86. package/locale-data/iu.js +1 -1
  87. package/locale-data/iw.js +1 -1
  88. package/locale-data/ja.js +1 -1
  89. package/locale-data/jbo.js +1 -1
  90. package/locale-data/jgo.js +1 -1
  91. package/locale-data/ji.js +1 -1
  92. package/locale-data/jmc.js +1 -1
  93. package/locale-data/jv.js +1 -1
  94. package/locale-data/jw.js +1 -1
  95. package/locale-data/ka.js +1 -1
  96. package/locale-data/kab.js +1 -1
  97. package/locale-data/kaj.js +1 -1
  98. package/locale-data/kam.js +1 -1
  99. package/locale-data/kcg.js +1 -1
  100. package/locale-data/kde.js +1 -1
  101. package/locale-data/kea.js +1 -1
  102. package/locale-data/khq.js +1 -1
  103. package/locale-data/ki.js +1 -1
  104. package/locale-data/kk.js +1 -1
  105. package/locale-data/kkj.js +1 -1
  106. package/locale-data/kl.js +1 -1
  107. package/locale-data/kln.js +1 -1
  108. package/locale-data/km.js +1 -1
  109. package/locale-data/kn.js +1 -1
  110. package/locale-data/ko.js +1 -1
  111. package/locale-data/kok.js +1 -1
  112. package/locale-data/ks.js +1 -1
  113. package/locale-data/ksb.js +1 -1
  114. package/locale-data/ksf.js +1 -1
  115. package/locale-data/ksh.js +1 -1
  116. package/locale-data/ku.js +1 -1
  117. package/locale-data/kw.js +1 -1
  118. package/locale-data/ky.js +1 -1
  119. package/locale-data/lag.js +1 -1
  120. package/locale-data/lb.js +1 -1
  121. package/locale-data/lg.js +1 -1
  122. package/locale-data/lkt.js +1 -1
  123. package/locale-data/ln.js +1 -1
  124. package/locale-data/lo.js +1 -1
  125. package/locale-data/lrc.js +1 -1
  126. package/locale-data/lt.js +1 -1
  127. package/locale-data/lu.js +1 -1
  128. package/locale-data/luo.js +1 -1
  129. package/locale-data/luy.js +1 -1
  130. package/locale-data/lv.js +1 -1
  131. package/locale-data/mas.js +1 -1
  132. package/locale-data/mer.js +1 -1
  133. package/locale-data/mfe.js +1 -1
  134. package/locale-data/mg.js +1 -1
  135. package/locale-data/mgh.js +1 -1
  136. package/locale-data/mgo.js +1 -1
  137. package/locale-data/mk.js +1 -1
  138. package/locale-data/ml.js +1 -1
  139. package/locale-data/mn.js +1 -1
  140. package/locale-data/mo.js +1 -1
  141. package/locale-data/mr.js +1 -1
  142. package/locale-data/ms.js +1 -1
  143. package/locale-data/mt.js +1 -1
  144. package/locale-data/mua.js +1 -1
  145. package/locale-data/my.js +1 -1
  146. package/locale-data/mzn.js +1 -1
  147. package/locale-data/nah.js +1 -1
  148. package/locale-data/naq.js +1 -1
  149. package/locale-data/nb.js +1 -1
  150. package/locale-data/nd.js +1 -1
  151. package/locale-data/nds.js +1 -0
  152. package/locale-data/ne.js +1 -1
  153. package/locale-data/nl.js +1 -1
  154. package/locale-data/nmg.js +1 -1
  155. package/locale-data/nn.js +1 -1
  156. package/locale-data/nnh.js +1 -1
  157. package/locale-data/no.js +1 -1
  158. package/locale-data/nqo.js +1 -1
  159. package/locale-data/nr.js +1 -1
  160. package/locale-data/nso.js +1 -1
  161. package/locale-data/nus.js +1 -1
  162. package/locale-data/ny.js +1 -1
  163. package/locale-data/nyn.js +1 -1
  164. package/locale-data/om.js +1 -1
  165. package/locale-data/or.js +1 -1
  166. package/locale-data/os.js +1 -1
  167. package/locale-data/pa.js +1 -1
  168. package/locale-data/pap.js +1 -1
  169. package/locale-data/pl.js +1 -1
  170. package/locale-data/prg.js +1 -1
  171. package/locale-data/ps.js +1 -1
  172. package/locale-data/pt.js +1 -1
  173. package/locale-data/qu.js +1 -1
  174. package/locale-data/rm.js +1 -1
  175. package/locale-data/rn.js +1 -1
  176. package/locale-data/ro.js +1 -1
  177. package/locale-data/rof.js +1 -1
  178. package/locale-data/ru.js +1 -1
  179. package/locale-data/rw.js +1 -1
  180. package/locale-data/rwk.js +1 -1
  181. package/locale-data/sah.js +1 -1
  182. package/locale-data/saq.js +1 -1
  183. package/locale-data/sbp.js +1 -1
  184. package/locale-data/sdh.js +1 -1
  185. package/locale-data/se.js +1 -1
  186. package/locale-data/seh.js +1 -1
  187. package/locale-data/ses.js +1 -1
  188. package/locale-data/sg.js +1 -1
  189. package/locale-data/sh.js +1 -1
  190. package/locale-data/shi.js +1 -1
  191. package/locale-data/si.js +1 -1
  192. package/locale-data/sk.js +1 -1
  193. package/locale-data/sl.js +1 -1
  194. package/locale-data/sma.js +1 -1
  195. package/locale-data/smi.js +1 -1
  196. package/locale-data/smj.js +1 -1
  197. package/locale-data/smn.js +1 -1
  198. package/locale-data/sms.js +1 -1
  199. package/locale-data/sn.js +1 -1
  200. package/locale-data/so.js +1 -1
  201. package/locale-data/sq.js +1 -1
  202. package/locale-data/sr.js +1 -1
  203. package/locale-data/ss.js +1 -1
  204. package/locale-data/ssy.js +1 -1
  205. package/locale-data/st.js +1 -1
  206. package/locale-data/sv.js +1 -1
  207. package/locale-data/sw.js +1 -1
  208. package/locale-data/syr.js +1 -1
  209. package/locale-data/ta.js +1 -1
  210. package/locale-data/te.js +1 -1
  211. package/locale-data/teo.js +1 -1
  212. package/locale-data/th.js +1 -1
  213. package/locale-data/ti.js +1 -1
  214. package/locale-data/tig.js +1 -1
  215. package/locale-data/tk.js +1 -1
  216. package/locale-data/tl.js +1 -1
  217. package/locale-data/tn.js +1 -1
  218. package/locale-data/to.js +1 -1
  219. package/locale-data/tr.js +1 -1
  220. package/locale-data/ts.js +1 -1
  221. package/locale-data/twq.js +1 -1
  222. package/locale-data/tzm.js +1 -1
  223. package/locale-data/ug.js +1 -1
  224. package/locale-data/uk.js +1 -1
  225. package/locale-data/ur.js +1 -1
  226. package/locale-data/uz.js +1 -1
  227. package/locale-data/vai.js +1 -1
  228. package/locale-data/ve.js +1 -1
  229. package/locale-data/vi.js +1 -1
  230. package/locale-data/vo.js +1 -1
  231. package/locale-data/vun.js +1 -1
  232. package/locale-data/wa.js +1 -1
  233. package/locale-data/wae.js +1 -1
  234. package/locale-data/wo.js +1 -1
  235. package/locale-data/xh.js +1 -1
  236. package/locale-data/xog.js +1 -1
  237. package/locale-data/yav.js +1 -1
  238. package/locale-data/yi.js +1 -1
  239. package/locale-data/yo.js +1 -1
  240. package/locale-data/yue.js +1 -0
  241. package/locale-data/zgh.js +1 -1
  242. package/locale-data/zh.js +1 -1
  243. package/locale-data/zu.js +1 -1
  244. package/package.json +11 -9
  245. package/src/components/date.js +47 -0
  246. package/src/components/html-message.js +88 -0
  247. package/src/components/message.js +137 -0
  248. package/src/components/number.js +47 -0
  249. package/src/components/plural.js +59 -0
  250. package/src/components/provider.js +177 -0
  251. package/src/components/relative.js +171 -0
  252. package/src/components/time.js +47 -0
  253. package/src/define-messages.js +11 -0
  254. package/src/en.js +2 -0
  255. package/src/format.js +276 -0
  256. package/src/index.js +12 -0
  257. package/src/inject.js +59 -0
  258. package/src/locale-data-registry.js +42 -0
  259. package/src/plural.js +28 -0
  260. package/src/react-intl.js +24 -0
  261. package/src/types.js +98 -0
  262. package/src/utils.js +103 -0
  263. package/yarn.lock +87 -59
package/src/format.js ADDED
@@ -0,0 +1,276 @@
1
+ /*
2
+ * Copyright 2015, Yahoo Inc.
3
+ * Copyrights licensed under the New BSD License.
4
+ * See the accompanying LICENSE file for terms.
5
+ */
6
+
7
+ import invariant from 'invariant';
8
+ import IntlRelativeFormat from 'intl-relativeformat';
9
+
10
+ import {
11
+ dateTimeFormatPropTypes,
12
+ numberFormatPropTypes,
13
+ relativeFormatPropTypes,
14
+ pluralFormatPropTypes,
15
+ } from './types';
16
+
17
+ import {escape, filterProps} from './utils';
18
+
19
+ const DATE_TIME_FORMAT_OPTIONS = Object.keys(dateTimeFormatPropTypes);
20
+ const NUMBER_FORMAT_OPTIONS = Object.keys(numberFormatPropTypes);
21
+ const RELATIVE_FORMAT_OPTIONS = Object.keys(relativeFormatPropTypes);
22
+ const PLURAL_FORMAT_OPTIONS = Object.keys(pluralFormatPropTypes);
23
+
24
+ const RELATIVE_FORMAT_THRESHOLDS = {
25
+ second: 60, // seconds to minute
26
+ minute: 60, // minutes to hour
27
+ hour: 24, // hours to day
28
+ day: 30, // days to month
29
+ month: 12, // months to year
30
+ };
31
+
32
+ function updateRelativeFormatThresholds(newThresholds) {
33
+ const {thresholds} = IntlRelativeFormat;
34
+ ({
35
+ second: thresholds.second,
36
+ minute: thresholds.minute,
37
+ hour: thresholds.hour,
38
+ day: thresholds.day,
39
+ month: thresholds.month,
40
+ } = newThresholds);
41
+ }
42
+
43
+ function getNamedFormat(formats, type, name) {
44
+ let format = formats && formats[type] && formats[type][name];
45
+ if (format) {
46
+ return format;
47
+ }
48
+
49
+ if (process.env.NODE_ENV !== 'production') {
50
+ console.error(`[React Intl] No ${type} format named: ${name}`);
51
+ }
52
+ }
53
+
54
+ export function formatDate(config, state, value, options = {}) {
55
+ const {locale, formats} = config;
56
+ const {format} = options;
57
+
58
+ let date = new Date(value);
59
+ let defaults = format && getNamedFormat(formats, 'date', format);
60
+ let filteredOptions = filterProps(
61
+ options,
62
+ DATE_TIME_FORMAT_OPTIONS,
63
+ defaults
64
+ );
65
+
66
+ try {
67
+ return state.getDateTimeFormat(locale, filteredOptions).format(date);
68
+ } catch (e) {
69
+ if (process.env.NODE_ENV !== 'production') {
70
+ console.error(`[React Intl] Error formatting date.\n${e}`);
71
+ }
72
+ }
73
+
74
+ return String(date);
75
+ }
76
+
77
+ export function formatTime(config, state, value, options = {}) {
78
+ const {locale, formats} = config;
79
+ const {format} = options;
80
+
81
+ let date = new Date(value);
82
+ let defaults = format && getNamedFormat(formats, 'time', format);
83
+ let filteredOptions = filterProps(
84
+ options,
85
+ DATE_TIME_FORMAT_OPTIONS,
86
+ defaults
87
+ );
88
+
89
+ if (
90
+ !filteredOptions.hour &&
91
+ !filteredOptions.minute &&
92
+ !filteredOptions.second
93
+ ) {
94
+ // Add default formatting options if hour, minute, or second isn't defined.
95
+ filteredOptions = {...filteredOptions, hour: 'numeric', minute: 'numeric'};
96
+ }
97
+
98
+ try {
99
+ return state.getDateTimeFormat(locale, filteredOptions).format(date);
100
+ } catch (e) {
101
+ if (process.env.NODE_ENV !== 'production') {
102
+ console.error(`[React Intl] Error formatting time.\n${e}`);
103
+ }
104
+ }
105
+
106
+ return String(date);
107
+ }
108
+
109
+ export function formatRelative(config, state, value, options = {}) {
110
+ const {locale, formats} = config;
111
+ const {format} = options;
112
+
113
+ let date = new Date(value);
114
+ let now = new Date(options.now);
115
+ let defaults = format && getNamedFormat(formats, 'relative', format);
116
+ let filteredOptions = filterProps(options, RELATIVE_FORMAT_OPTIONS, defaults);
117
+
118
+ // Capture the current threshold values, then temporarily override them with
119
+ // specific values just for this render.
120
+ const oldThresholds = {...IntlRelativeFormat.thresholds};
121
+ updateRelativeFormatThresholds(RELATIVE_FORMAT_THRESHOLDS);
122
+
123
+ try {
124
+ return state.getRelativeFormat(locale, filteredOptions).format(date, {
125
+ now: isFinite(now) ? now : state.now(),
126
+ });
127
+ } catch (e) {
128
+ if (process.env.NODE_ENV !== 'production') {
129
+ console.error(`[React Intl] Error formatting relative time.\n${e}`);
130
+ }
131
+ } finally {
132
+ updateRelativeFormatThresholds(oldThresholds);
133
+ }
134
+
135
+ return String(date);
136
+ }
137
+
138
+ export function formatNumber(config, state, value, options = {}) {
139
+ const {locale, formats} = config;
140
+ const {format} = options;
141
+
142
+ let defaults = format && getNamedFormat(formats, 'number', format);
143
+ let filteredOptions = filterProps(options, NUMBER_FORMAT_OPTIONS, defaults);
144
+
145
+ try {
146
+ return state.getNumberFormat(locale, filteredOptions).format(value);
147
+ } catch (e) {
148
+ if (process.env.NODE_ENV !== 'production') {
149
+ console.error(`[React Intl] Error formatting number.\n${e}`);
150
+ }
151
+ }
152
+
153
+ return String(value);
154
+ }
155
+
156
+ export function formatPlural(config, state, value, options = {}) {
157
+ const {locale} = config;
158
+
159
+ let filteredOptions = filterProps(options, PLURAL_FORMAT_OPTIONS);
160
+
161
+ try {
162
+ return state.getPluralFormat(locale, filteredOptions).format(value);
163
+ } catch (e) {
164
+ if (process.env.NODE_ENV !== 'production') {
165
+ console.error(`[React Intl] Error formatting plural.\n${e}`);
166
+ }
167
+ }
168
+
169
+ return 'other';
170
+ }
171
+
172
+ export function formatMessage(
173
+ config,
174
+ state,
175
+ messageDescriptor = {},
176
+ values = {}
177
+ ) {
178
+ const {locale, formats, messages, defaultLocale, defaultFormats} = config;
179
+
180
+ const {id, defaultMessage} = messageDescriptor;
181
+
182
+ // `id` is a required field of a Message Descriptor.
183
+ invariant(id, '[React Intl] An `id` must be provided to format a message.');
184
+
185
+ const message = messages && messages[id];
186
+ const hasValues = Object.keys(values).length > 0;
187
+
188
+ // Avoid expensive message formatting for simple messages without values. In
189
+ // development messages will always be formatted in case of missing values.
190
+ if (!hasValues && process.env.NODE_ENV === 'production') {
191
+ return message || defaultMessage || id;
192
+ }
193
+
194
+ let formattedMessage;
195
+
196
+ if (message) {
197
+ try {
198
+ let formatter = state.getMessageFormat(message, locale, formats);
199
+
200
+ formattedMessage = formatter.format(values);
201
+ } catch (e) {
202
+ if (process.env.NODE_ENV !== 'production') {
203
+ console.error(
204
+ `[React Intl] Error formatting message: "${id}" for locale: "${locale}"` +
205
+ (defaultMessage ? ', using default message as fallback.' : '') +
206
+ `\n${e}`
207
+ );
208
+ }
209
+ }
210
+ } else {
211
+ if (process.env.NODE_ENV !== 'production') {
212
+ // This prevents warnings from littering the console in development
213
+ // when no `messages` are passed into the <IntlProvider> for the
214
+ // default locale, and a default message is in the source.
215
+ if (
216
+ !defaultMessage ||
217
+ (locale && locale.toLowerCase() !== defaultLocale.toLowerCase())
218
+ ) {
219
+ console.error(
220
+ `[React Intl] Missing message: "${id}" for locale: "${locale}"` +
221
+ (defaultMessage ? ', using default message as fallback.' : '')
222
+ );
223
+ }
224
+ }
225
+ }
226
+
227
+ if (!formattedMessage && defaultMessage) {
228
+ try {
229
+ let formatter = state.getMessageFormat(
230
+ defaultMessage,
231
+ defaultLocale,
232
+ defaultFormats
233
+ );
234
+
235
+ formattedMessage = formatter.format(values);
236
+ } catch (e) {
237
+ if (process.env.NODE_ENV !== 'production') {
238
+ console.error(
239
+ `[React Intl] Error formatting the default message for: "${id}"` +
240
+ `\n${e}`
241
+ );
242
+ }
243
+ }
244
+ }
245
+
246
+ if (!formattedMessage) {
247
+ if (process.env.NODE_ENV !== 'production') {
248
+ console.error(
249
+ `[React Intl] Cannot format message: "${id}", ` +
250
+ `using message ${message || defaultMessage
251
+ ? 'source'
252
+ : 'id'} as fallback.`
253
+ );
254
+ }
255
+ }
256
+
257
+ return formattedMessage || message || defaultMessage || id;
258
+ }
259
+
260
+ export function formatHTMLMessage(
261
+ config,
262
+ state,
263
+ messageDescriptor,
264
+ rawValues = {}
265
+ ) {
266
+ // Process all the values before they are used when formatting the ICU
267
+ // Message string. Since the formatted message might be injected via
268
+ // `innerHTML`, all String-based values need to be HTML-escaped.
269
+ let escapedValues = Object.keys(rawValues).reduce((escaped, name) => {
270
+ let value = rawValues[name];
271
+ escaped[name] = typeof value === 'string' ? escape(value) : value;
272
+ return escaped;
273
+ }, {});
274
+
275
+ return formatMessage(config, state, messageDescriptor, escapedValues);
276
+ }
package/src/index.js ADDED
@@ -0,0 +1,12 @@
1
+ /*
2
+ * Copyright 2015, Yahoo Inc.
3
+ * Copyrights licensed under the New BSD License.
4
+ * See the accompanying LICENSE file for terms.
5
+ */
6
+
7
+ import allLocaleData from '../locale-data/index';
8
+ import {addLocaleData} from './react-intl';
9
+
10
+ export * from './react-intl';
11
+
12
+ addLocaleData(allLocaleData);
package/src/inject.js ADDED
@@ -0,0 +1,59 @@
1
+ /*
2
+ * Copyright 2015, Yahoo Inc.
3
+ * Copyrights licensed under the New BSD License.
4
+ * See the accompanying LICENSE file for terms.
5
+ */
6
+
7
+ // Inspired by react-redux's `connect()` HOC factory function implementation:
8
+ // https://github.com/rackt/react-redux
9
+
10
+ import React, {Component} from 'react';
11
+ import invariant from 'invariant';
12
+ import {intlShape} from './types';
13
+ import {invariantIntlContext} from './utils';
14
+
15
+ function getDisplayName(Component) {
16
+ return Component.displayName || Component.name || 'Component';
17
+ }
18
+
19
+ export default function injectIntl(WrappedComponent, options = {}) {
20
+ const {intlPropName = 'intl', withRef = false} = options;
21
+
22
+ class InjectIntl extends Component {
23
+ static displayName = `InjectIntl(${getDisplayName(WrappedComponent)})`;
24
+
25
+ static contextTypes = {
26
+ intl: intlShape,
27
+ };
28
+
29
+ static WrappedComponent = WrappedComponent;
30
+
31
+ constructor(props, context) {
32
+ super(props, context);
33
+ invariantIntlContext(context);
34
+ }
35
+
36
+ getWrappedInstance() {
37
+ invariant(
38
+ withRef,
39
+ '[React Intl] To access the wrapped instance, ' +
40
+ 'the `{withRef: true}` option must be set when calling: ' +
41
+ '`injectIntl()`'
42
+ );
43
+
44
+ return this.refs.wrappedInstance;
45
+ }
46
+
47
+ render() {
48
+ return (
49
+ <WrappedComponent
50
+ {...this.props}
51
+ {...{[intlPropName]: this.context.intl}}
52
+ ref={withRef ? 'wrappedInstance' : null}
53
+ />
54
+ );
55
+ }
56
+ }
57
+
58
+ return InjectIntl;
59
+ }
@@ -0,0 +1,42 @@
1
+ /*
2
+ * Copyright 2015, Yahoo Inc.
3
+ * Copyrights licensed under the New BSD License.
4
+ * See the accompanying LICENSE file for terms.
5
+ */
6
+
7
+ import IntlMessageFormat from 'intl-messageformat';
8
+ import IntlRelativeFormat from 'intl-relativeformat';
9
+
10
+ export function addLocaleData(data = []) {
11
+ let locales = Array.isArray(data) ? data : [data];
12
+
13
+ locales.forEach(localeData => {
14
+ if (localeData && localeData.locale) {
15
+ IntlMessageFormat.__addLocaleData(localeData);
16
+ IntlRelativeFormat.__addLocaleData(localeData);
17
+ }
18
+ });
19
+ }
20
+
21
+ export function hasLocaleData(locale) {
22
+ let localeParts = (locale || '').split('-');
23
+
24
+ while (localeParts.length > 0) {
25
+ if (hasIMFAndIRFLocaleData(localeParts.join('-'))) {
26
+ return true;
27
+ }
28
+
29
+ localeParts.pop();
30
+ }
31
+
32
+ return false;
33
+ }
34
+
35
+ function hasIMFAndIRFLocaleData(locale) {
36
+ let normalizedLocale = locale && locale.toLowerCase();
37
+
38
+ return !!(
39
+ IntlMessageFormat.__localeData__[normalizedLocale] &&
40
+ IntlRelativeFormat.__localeData__[normalizedLocale]
41
+ );
42
+ }
package/src/plural.js ADDED
@@ -0,0 +1,28 @@
1
+ /*
2
+ * Copyright 2015, Yahoo Inc.
3
+ * Copyrights licensed under the New BSD License.
4
+ * See the accompanying LICENSE file for terms.
5
+ */
6
+
7
+ // This is a "hack" until a proper `intl-pluralformat` package is created.
8
+
9
+ import IntlMessageFormat from 'intl-messageformat';
10
+
11
+ function resolveLocale(locales) {
12
+ // IntlMessageFormat#_resolveLocale() does not depend on `this`.
13
+ return IntlMessageFormat.prototype._resolveLocale(locales);
14
+ }
15
+
16
+ function findPluralFunction(locale) {
17
+ // IntlMessageFormat#_findPluralFunction() does not depend on `this`.
18
+ return IntlMessageFormat.prototype._findPluralRuleFunction(locale);
19
+ }
20
+
21
+ export default class IntlPluralFormat {
22
+ constructor(locales, options = {}) {
23
+ let useOrdinal = options.style === 'ordinal';
24
+ let pluralFn = findPluralFunction(resolveLocale(locales));
25
+
26
+ this.format = value => pluralFn(value, useOrdinal);
27
+ }
28
+ }
@@ -0,0 +1,24 @@
1
+ /*
2
+ * Copyright 2015, Yahoo Inc.
3
+ * Copyrights licensed under the New BSD License.
4
+ * See the accompanying LICENSE file for terms.
5
+ */
6
+
7
+ import defaultLocaleData from './en';
8
+ import {addLocaleData} from './locale-data-registry';
9
+
10
+ addLocaleData(defaultLocaleData);
11
+
12
+ export {addLocaleData};
13
+ export {intlShape} from './types';
14
+ export {default as injectIntl} from './inject';
15
+ export {default as defineMessages} from './define-messages';
16
+
17
+ export {default as IntlProvider} from './components/provider';
18
+ export {default as FormattedDate} from './components/date';
19
+ export {default as FormattedTime} from './components/time';
20
+ export {default as FormattedRelative} from './components/relative';
21
+ export {default as FormattedNumber} from './components/number';
22
+ export {default as FormattedPlural} from './components/plural';
23
+ export {default as FormattedMessage} from './components/message';
24
+ export {default as FormattedHTMLMessage} from './components/html-message';
package/src/types.js ADDED
@@ -0,0 +1,98 @@
1
+ /*
2
+ * Copyright 2015, Yahoo Inc.
3
+ * Copyrights licensed under the New BSD License.
4
+ * See the accompanying LICENSE file for terms.
5
+ */
6
+
7
+ import PropTypes from 'prop-types';
8
+
9
+ const {
10
+ bool,
11
+ number,
12
+ string,
13
+ func,
14
+ object,
15
+ oneOf,
16
+ shape,
17
+ any,
18
+ oneOfType,
19
+ } = PropTypes;
20
+ const localeMatcher = oneOf(['best fit', 'lookup']);
21
+ const narrowShortLong = oneOf(['narrow', 'short', 'long']);
22
+ const numeric2digit = oneOf(['numeric', '2-digit']);
23
+ const funcReq = func.isRequired;
24
+
25
+ export const intlConfigPropTypes = {
26
+ locale: string,
27
+ formats: object,
28
+ messages: object,
29
+ textComponent: any,
30
+
31
+ defaultLocale: string,
32
+ defaultFormats: object,
33
+ };
34
+
35
+ export const intlFormatPropTypes = {
36
+ formatDate: funcReq,
37
+ formatTime: funcReq,
38
+ formatRelative: funcReq,
39
+ formatNumber: funcReq,
40
+ formatPlural: funcReq,
41
+ formatMessage: funcReq,
42
+ formatHTMLMessage: funcReq,
43
+ };
44
+
45
+ export const intlShape = shape({
46
+ ...intlConfigPropTypes,
47
+ ...intlFormatPropTypes,
48
+ formatters: object,
49
+ now: funcReq,
50
+ });
51
+
52
+ export const messageDescriptorPropTypes = {
53
+ id: string.isRequired,
54
+ description: oneOfType([string, object]),
55
+ defaultMessage: string,
56
+ };
57
+
58
+ export const dateTimeFormatPropTypes = {
59
+ localeMatcher,
60
+ formatMatcher: oneOf(['basic', 'best fit']),
61
+
62
+ timeZone: string,
63
+ hour12: bool,
64
+
65
+ weekday: narrowShortLong,
66
+ era: narrowShortLong,
67
+ year: numeric2digit,
68
+ month: oneOf(['numeric', '2-digit', 'narrow', 'short', 'long']),
69
+ day: numeric2digit,
70
+ hour: numeric2digit,
71
+ minute: numeric2digit,
72
+ second: numeric2digit,
73
+ timeZoneName: oneOf(['short', 'long']),
74
+ };
75
+
76
+ export const numberFormatPropTypes = {
77
+ localeMatcher,
78
+
79
+ style: oneOf(['decimal', 'currency', 'percent']),
80
+ currency: string,
81
+ currencyDisplay: oneOf(['symbol', 'code', 'name']),
82
+ useGrouping: bool,
83
+
84
+ minimumIntegerDigits: number,
85
+ minimumFractionDigits: number,
86
+ maximumFractionDigits: number,
87
+ minimumSignificantDigits: number,
88
+ maximumSignificantDigits: number,
89
+ };
90
+
91
+ export const relativeFormatPropTypes = {
92
+ style: oneOf(['best fit', 'numeric']),
93
+ units: oneOf(['second', 'minute', 'hour', 'day', 'month', 'year']),
94
+ };
95
+
96
+ export const pluralFormatPropTypes = {
97
+ style: oneOf(['cardinal', 'ordinal']),
98
+ };
package/src/utils.js ADDED
@@ -0,0 +1,103 @@
1
+ /*
2
+ HTML escaping and shallow-equals implementations are the same as React's
3
+ (on purpose.) Therefore, it has the following Copyright and Licensing:
4
+
5
+ Copyright 2013-2014, Facebook, Inc.
6
+ All rights reserved.
7
+
8
+ This source code is licensed under the BSD-style license found in the LICENSE
9
+ file in the root directory of React's source tree.
10
+ */
11
+
12
+ import invariant from 'invariant';
13
+ import {intlConfigPropTypes} from './types';
14
+
15
+ const intlConfigPropNames = Object.keys(intlConfigPropTypes);
16
+
17
+ const ESCAPED_CHARS = {
18
+ '&': '&amp;',
19
+ '>': '&gt;',
20
+ '<': '&lt;',
21
+ '"': '&quot;',
22
+ "'": '&#x27;',
23
+ };
24
+
25
+ const UNSAFE_CHARS_REGEX = /[&><"']/g;
26
+
27
+ export function escape(str) {
28
+ return ('' + str).replace(UNSAFE_CHARS_REGEX, match => ESCAPED_CHARS[match]);
29
+ }
30
+
31
+ export function filterProps(props, whitelist, defaults = {}) {
32
+ return whitelist.reduce((filtered, name) => {
33
+ if (props.hasOwnProperty(name)) {
34
+ filtered[name] = props[name];
35
+ } else if (defaults.hasOwnProperty(name)) {
36
+ filtered[name] = defaults[name];
37
+ }
38
+
39
+ return filtered;
40
+ }, {});
41
+ }
42
+
43
+ export function invariantIntlContext({intl} = {}) {
44
+ invariant(
45
+ intl,
46
+ '[React Intl] Could not find required `intl` object. ' +
47
+ '<IntlProvider> needs to exist in the component ancestry.'
48
+ );
49
+ }
50
+
51
+ export function shallowEquals(objA, objB) {
52
+ if (objA === objB) {
53
+ return true;
54
+ }
55
+
56
+ if (
57
+ typeof objA !== 'object' ||
58
+ objA === null ||
59
+ typeof objB !== 'object' ||
60
+ objB === null
61
+ ) {
62
+ return false;
63
+ }
64
+
65
+ let keysA = Object.keys(objA);
66
+ let keysB = Object.keys(objB);
67
+
68
+ if (keysA.length !== keysB.length) {
69
+ return false;
70
+ }
71
+
72
+ // Test for A's keys different from B.
73
+ let bHasOwnProperty = Object.prototype.hasOwnProperty.bind(objB);
74
+ for (let i = 0; i < keysA.length; i++) {
75
+ if (!bHasOwnProperty(keysA[i]) || objA[keysA[i]] !== objB[keysA[i]]) {
76
+ return false;
77
+ }
78
+ }
79
+
80
+ return true;
81
+ }
82
+
83
+ export function shouldIntlComponentUpdate(
84
+ {props, state, context = {}},
85
+ nextProps,
86
+ nextState,
87
+ nextContext = {}
88
+ ) {
89
+ const {intl = {}} = context;
90
+ const {intl: nextIntl = {}} = nextContext;
91
+
92
+ return (
93
+ !shallowEquals(nextProps, props) ||
94
+ !shallowEquals(nextState, state) ||
95
+ !(
96
+ nextIntl === intl ||
97
+ shallowEquals(
98
+ filterProps(nextIntl, intlConfigPropNames),
99
+ filterProps(intl, intlConfigPropNames)
100
+ )
101
+ )
102
+ );
103
+ }