You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The most simple case of MessageFormat would involve no formatting. Just a string passthrough. This sounds silly, but often it's nice to always use the same i18n system when doing translations, and not everything takes variables.
13
+
14
+
The simplest case of MessageFormat involves no formatting, just a string passthrough. This may sound silly, but often it's nice to always use the same message formatting system when doing translations, and not everything requires variables.
9
15
10
16
```javascript
11
-
// Insantiate a MessageFormat object on your locale
12
17
var mf =newMessageFormat('en');
18
+
var message =mf.compile('This is a message.');
13
19
14
-
// Compile a message
15
-
var message =mf.compile( 'This is a message.' ); // returns a function
16
-
17
-
// You can call the function to get data out
18
-
>message();
19
-
"This is a message."
20
+
message();
21
+
// "This is a message."
22
+
```
20
23
21
-
//NOTE:: if a message _does_ require data to be passed in, an error is thrown if you do not.
24
+
NOTE: if a message _does_ require data to be passed in, an error is thrown if you do not.
22
25
23
-
```
24
26
25
-
## Simple Variable Replacement
27
+
## Variables
26
28
27
-
The second most simple way to use MessageFormat is for simple variable replacement. MessageFormat looks odd at first, but it's actually fairly simple. One way to think about the `{` and `}` is that every level of them bring you into and out-of `literal` and `code` mode.
29
+
The second most simple way to use MessageFormat is for simple variable replacement. MessageFormat may look odd at first, but it's actually fairly simple. One way to think about the `{` and `}` is that every level of them bring you into and out-of `literal` and `code` mode.
28
30
29
31
By default (like in the previous example), you are just writing a literal. Then the first level of brackets brings you into one of several data-driven situations. The most simple is variable replacement.
30
32
31
33
Simply putting a variable name in between `{` and `}` will place that variable there in the output.
32
34
33
35
```javascript
34
-
// Instantiate new MessageFormat object for your locale
35
36
var mf =newMessageFormat('en');
37
+
var varMessage =mf.compile('His name is {NAME}.');
36
38
37
-
// Compile a message
38
-
var message =mf.compile('His name is {NAME}.');
39
-
40
-
// Then send that data into the function
41
-
>message({ "NAME":"Jed" });
42
-
"His name is Jed."
43
-
44
-
// NOTE:: it's best to try and stick to keys that would be natively
45
-
// tolerant in your JS runtimes (think valid JS variable names).
39
+
varMessage({ NAME:"Jed" });
40
+
// "His name is Jed."
46
41
```
47
42
48
-
## SelectFormat
49
-
50
-
`SelectFormat` is a lot like a switch statement for your messages. Most often it's used to select gender in a string. Here's an example:
51
-
52
-
```javascript
53
-
// Insantiate an instance with your language settings
54
-
var mf =newMesssageFormat('en');
55
-
// Compile a message - returns a function
56
-
var message =mf.compile('{GENDER, select, male{He} female{She} other{They}} liked this.');
57
-
58
-
// Run your message function with your data
59
-
>message({"GENDER":"male"});
60
-
"He liked this."
61
-
62
-
>message({"GENDER":"female"});
63
-
"She liked this."
64
43
65
-
// The 'other' key is **required** and in the case of GENDER
66
-
// it should be phrased as if you are too far away to tell the gender of the subject.
67
-
>message({});
68
-
"They liked this."
69
-
70
-
```
44
+
## SelectFormat
71
45
72
-
## PluralFormat
46
+
`SelectFormat` is a lot like a switch statement for your messages. Often it's used to select gender in a string. The format of the statement is `{varname, select, thisvalue{...} thatvalue{...} other{...}}`, where `varname` matches a key in the data you give to the resulting function, and `'thisvalue'` & `'thatvalue'` are some of the string-equivalent values that it may have. The `other` key is required, and is selected if no other case matches.
73
47
74
-
`PluralFormat`is a similar mechanism to `SelectFormat` (especially syntax wise), but it's specific to numbers, and the key that is chosen is generated by a _Plural Function_.
48
+
Note that comparison is made using the JavaScript `==` operator, so if a key is left out of the input data, the case `undefined{...}` would match that.
75
49
76
50
```javascript
77
-
// Insantiate a new MessageFormat object
78
-
var mf =newMessageFormat('en');
79
-
80
-
// You can use the provided locales in the `/locale` folder
81
-
// (include the file directly after including messageformat.js
82
-
var mf =newMessageFormat( 'sl' );
83
-
84
-
// OR - you can pass a custom plural function to the MessageFormat constructor function.
85
-
var mf =newMessage( 'requiredCustomName', function (n) {
86
-
if ( n ===42 ) {
87
-
return'many';
88
-
}
89
-
return'other';
90
-
});
91
-
92
-
// Then the numbers that are passed into a compiled message will run through this function to select
93
-
// the keys. This is for the 'en' locale:
94
-
var message =mf.compile('There {NUM_RESULTS, plural, one{is one result} other{are # results}}.');
ICU declares the 6 named keys that CLDR defines for their plural form data. Those are:
112
-
113
-
* zero
114
-
* one
115
-
* two
116
-
* few
117
-
* many
118
-
* other (**required**)
119
-
120
-
All of them are fairly straight-forward, but do remember, that for some languages, they are more loose "guidelines" than they are exact.
121
-
122
-
The only **required** key is `other`. Your compilation will throw an error if you forget this. In english, and many other languages, the logic is simple:
67
+
## PluralFormat
123
68
124
-
`If N equals 1, then ONE, otherwise OTHER`
69
+
`PluralFormat` is a similar mechanism to `SelectFormat`, but specific to numerical values. The key that is chosen is generated from the specified input variable by a locale-specific _plural function_.
125
70
126
-
Other languages (take a peak at `ar.js` or `sl.js`) can get much more complicated.
71
+
The numeric input is mapped to a plural category, some subset of `zero`, `one`, `two`, `few`, `many`, and `other` depending on the locale and the type of plural. English, for instance, uses `one` and `other` for cardinal plurals (one result, many results) and `one`, `two`, `few`, and `other` for ordinal plurals (1st result, 2nd result, etc). For information on which keys are used by your locale, please refer to the [CLDR table of plural rules](http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html).
127
72
128
-
**Note:** English only uses `one` and `other` for cardinal plurals, so including `zero` will never get called, even when the number is 0
73
+
Matches for exact values are available with the `=` prefix.
129
74
130
-
The most simple (to pluralize) languages have no pluralization rules an rely solely on the `other` named key.
75
+
The keyword for cardinal plurals is `plural`, and for ordinal plurals is `selectordinal`.
131
76
132
-
```
133
-
{NUM, plural,
134
-
zero {There are zero - in a lang that needs it.}
135
-
one {There is one - in a lang that has it.}
136
-
two {There is two - in a lang that has it.}
137
-
few {There are a few - in a lang that has it.}
138
-
many {There are many - in a lang that has it.}
139
-
other {There is a different amount than all the other stuff above.}
140
-
}
141
-
```
77
+
Within a plural statement, `#` will be replaced by the variable value.
142
78
143
-
### Literal Numeric Keys
79
+
```javascript
80
+
var mf =newMessageFormat('en');
81
+
var pluralMessage =mf.compile(
82
+
'There {NUM_RESULTS, plural, =0{are no results} one{is one result} other{are # results}}.'
83
+
);
144
84
145
-
There also exists the capability to put literal numbers as keys in a select statement. These are delimited by prefixing them with the `=` character. These will match single, specific numbers. If there is a match, that branch will immediately run, and the corresponding named key **will not** also run.
85
+
pluralMessage({ NUM_RESULTS:0 });
86
+
// "There are no results."
146
87
147
-
There are plenty of legitimate uses for this, especially when considering base cases and more pleasant language. But if you're a Douglas Adams fan, might use it like so:
88
+
pluralMessage({ NUM_RESULTS:1 });
89
+
// "There is one result."
148
90
91
+
pluralMessage({ NUM_RESULTS:100 });
92
+
// "There are 100 results."
149
93
```
150
-
You have {NUM_TASKS, plural,
151
-
one {one task}
152
-
other {# tasks}
153
-
=42 {the answer to the life, the universe and everything tasks}
154
-
} remaining.
155
-
```
156
-
157
-
When `NUM_TASKS` is 42, this outputs smiles. Remember, these have priority over the named keys.
158
-
159
-
### PluralFormat - offset extension
160
94
161
-
ICU provided the ability to extend existing select and plural functionality, and the only official extension (that I could find) is the `offset` extension.
162
95
163
-
It goes after the `plural` declaration, and is used to generate sentences that break up a number into multiple sections. For instance:
96
+
#### Offset extension
164
97
165
-
> You and 4 others added this to their profiles.
166
-
167
-
In this case, the total number of people who added 'this' to their profiles is actually 5. We can use the `offset` extension to help us with this.
98
+
To generate sentences such as "You and 4 others added this to their profiles.", PluralFormat supports adding an `offset` to the variable value before determining its plural category. Literal/exact matches are tested before applying the offset.
168
99
169
100
```javascript
170
101
var mf =newMessageFormat('en');
171
102
172
-
// For simplicity's sake, let's assume the base case here isn't silly.
173
-
// The test suite has a bigger offset example at the bottom
174
-
// Let's also assume neutral gender for the same reason
175
-
176
-
// Set the offset to 1
177
-
var message =mf.compile(
103
+
var offsetMessage =mf.compile(
178
104
'You {NUM_ADDS, plural, offset:1'+
179
-
'=0{didnt add this to your profile}'+// Number literals, with a `=` do **NOT** use
180
-
'=1{added this to your profile}'+// the offset value
181
-
'one{and one other person added this to their profile}'+
182
-
'other{and # others added this to their profiles}'+
183
-
'}.'
105
+
'=0{did not add this}'+
106
+
'=1{added this}'+
107
+
'one{and one other person added this}'+
108
+
'other{and # others added this}'+
109
+
'}.'
184
110
);
185
111
186
-
// Tip: I like to consider the `=` prefixed number literals as more of an "inductive step"
187
-
// e.g. in this case, since (0 - 1) is _negative_ 1, we want to handle that base case.
188
-
189
-
>message({"NUM_ADDS":0 });
190
-
"You didnt add this to your profile."
191
-
192
-
>message({"NUM_ADDS":1 });
193
-
"You added this to your profile."
112
+
offsetMessage({ NUM_ADDS:0 });
113
+
// "You did not add this."
194
114
195
-
>message({"NUM_ADDS":2 });
196
-
"You and one other person added this to their profile."
115
+
offsetMessage({ NUM_ADDS:1 });
116
+
// "You added this."
197
117
198
-
>message({"NUM_ADDS":3 });
199
-
"You and 2 others added this to their profile."
118
+
offsetMessage({ NUM_ADDS:2 });
119
+
//"You and one other person added this."
200
120
121
+
offsetMessage({ NUM_ADDS:3 });
122
+
// "You and 2 others added this."
201
123
```
202
124
125
+
203
126
## Nesting
204
127
205
-
Very simply, you can nest both `SelectFormat` blocks into `PluralFormat` blocks, and visa-versa, as deeply as you'd like. Simply start the new block directly inside:
128
+
All types of messageformat statements may be nested within each other, to unlimited depth:
206
129
207
-
```
130
+
```text
208
131
{SEL1, select,
209
132
other {
210
133
{PLUR1, plural,
211
134
one {1}
212
135
other {
213
136
{SEL2, select,
214
-
other {deep in the heart.}
137
+
other {Deep in the heart.}
215
138
}
216
139
}
217
140
}
218
141
}
219
142
}
220
143
```
221
144
222
-
## Escaping
223
145
224
-
messageformat.js tries to a good job of being tolerant of as much as possible, but some characters, like the ones used the actual MessageFormat spec itself, must be escaped to be a part of your string.
146
+
## Escaping
225
147
226
-
For `{`, `}`and `#` (only inside of a select value) literals, just escape them with a backslash. (If you are in a JS string, you'll need to escape the escape backslash so it'll look like two).
148
+
The characters `{` and `}`must be escaped with a `\` to be included in the output as literal characters. Within plural statements, `#` must also be similarly escaped. Keep in mind that you'll need to double-escape with `\\` within e.g. JavaScript and JSON strings.
227
149
228
150
```javascript
229
-
// Technically, it's just:
230
-
231
-
\{\}\#
232
-
233
-
// But in practice, since you're often dealing with string literals, it looks more like
234
-
235
-
var msg =mf.compile("\\{ {S, select, other{# is a \\#}} \\}");
151
+
var mf =newMessageFormat('en');
152
+
var escMessage =mf.compile('\\{ {S, plural, other{# is a \\#}} \\}');
0 commit comments