UNPKG

2.86 kBJSXView Raw
1import React from 'react';
2
3
4// TODO: default locale should be empty, not fake-English
5var state = {
6 messages: {},
7 locale: {name: 'en', pluralFn: (c) => c === 1 ? 'one' : 'other'}
8};
9
10
11function setMessages(messages) {
12 state.messages = messages;
13}
14
15function setLocale(locale) {
16 state.locale = locale;
17}
18
19
20function i18n(original) {
21 let translated = state.messages[original];
22 return translated ? translated() : original;
23}
24
25
26class I18N extends React.Component {
27 render() {
28 let renderer = state.messages[this.props.message];
29 if (renderer) {
30 let rendered = renderer.apply(this.props.context, this.props.args);
31 // TODO: this check would be unnecessary if collisions between
32 // source and react child strings were impossible.
33 if (Object.prototype.toString.call(rendered) === '[object String]') {
34 return <span>{rendered}</span>;
35 } else {
36 return rendered;
37 }
38 }
39 return this.props.fallback.call(this.props.context);
40 }
41}
42
43
44class Match extends React.Component {
45 render() {
46 return <span>{this.props.children}</span>;
47 }
48}
49
50Match._isMatch = true;
51Match.propTypes = {
52 when: React.PropTypes.string
53};
54
55
56class Pluralize extends React.Component {
57
58 classifyMatch(match) {
59 if (match && match.startsWith('=')) {
60 return parseInt(match.slice(1), 10);
61 } else {
62 return match;
63 }
64 }
65
66 classifyMatches(matches, match) {
67 matches[this.classifyMatch(match.props.when)] = match;
68 return matches;
69 }
70
71 render() {
72 // TODO: this probably should happen in componentWillMount,
73 // it is not likely useful to allow for dynamic children of Pluralize.
74 let children = [];
75 React.Children.forEach(this.props.children, c => children.push(c));
76 children = children.reduce(this.classifyMatches.bind(this), {});
77
78 let form = state.locale.pluralFn(this.props.on);
79 let match = children[this.props.on] || children[form];
80 if (!match) {
81 throw new Error("Missing plural form: " + form);
82 }
83 return match;
84 }
85}
86
87
88Pluralize.propTypes = {
89 on: React.PropTypes.number,
90 children: (props, propName, componentName) => {
91 let nonTextChildren = props[propName].filter(c => Object.prototype.toString.call(c) !== '[object String]');
92 let nonMatchChildren = nonTextChildren.filter(c => !c.type._isMatch);
93 if (nonMatchChildren.length) {
94 return new Error("Pluralize given children other than a Match: " + nonMatchChildren.map(c => c.type.displayName || c.type.name || c.type));
95 }
96 }
97}
98
99
100export default {
101 i18n,
102 I18N,
103 setMessages,
104 setLocale,
105 Pluralize,
106 Match,
107 Format: ['Pluralize', 'Match']
108};