@@ -18,3 +18,248 @@ the local variable takes precedence.
18
18
19
19
It is an error for a local variable definition to
20
20
refer to a local variable that's defined after it in the message.
21
+
22
+ ## Error Handling
23
+
24
+ Errors in messages and their formatting may occur and be detected
25
+ at multiple different stages of their processing.
26
+ Where available,
27
+ the use of validation tools is recommended,
28
+ as early detection of errors makes their correction easier.
29
+
30
+ During the formatting of a message,
31
+ various errors may be encountered.
32
+ These are divided into the following categories:
33
+
34
+ - ** Syntax errors** occur when the syntax representation of a message is not well-formed.
35
+
36
+ Example invalid messages resulting in a Syntax error:
37
+
38
+ ```
39
+ {Missing end brace
40
+ ```
41
+
42
+ ```
43
+ {Unknown {#placeholder#}}
44
+ ```
45
+
46
+ ```
47
+ let $var = {(no message body)}
48
+ ```
49
+
50
+ - ** Data Model errors** occur when a message is invalid due to
51
+ violating one of the semantic requirements on its structure:
52
+
53
+ - ** Variant Key Mismatch errors** occur when the number of keys on a Variant
54
+ does not equal the number of Selectors.
55
+
56
+ Example invalid messages resulting in a Variant Key Mismatch error:
57
+
58
+ ```
59
+ match {$one}
60
+ when 1 2 {Too many}
61
+ when * {Otherwise}
62
+ ```
63
+
64
+ ```
65
+ match {$one} {$two}
66
+ when 1 2 {Two keys}
67
+ when * {Missing a key}
68
+ when * * {Otherwise}
69
+ ```
70
+
71
+ - **Missing Fallback Variant errors** occur when the message
72
+ does not include a Variant with only catch-all keys.
73
+
74
+ Example invalid messages resulting in a Missing Fallback Variant error:
75
+
76
+ ```
77
+ match {$one}
78
+ when 1 {Value is one}
79
+ when 2 {Value is two}
80
+ ```
81
+
82
+ ```
83
+ match {$one} {$two}
84
+ when 1 * {First is one}
85
+ when * 1 {Second is one}
86
+ ```
87
+
88
+ - **Resolution errors** occur when the runtime value of a part of a message
89
+ cannot be determined.
90
+
91
+ - **Unresolved Variable errors** occur when a variable reference cannot be resolved.
92
+
93
+ For example, attempting to format either of the following messages
94
+ must result in an Unresolved Variable error if done within a context that
95
+ does not provide for the variable reference `$var` to be successfully resolved:
96
+
97
+ ```
98
+ {The value is {$var}.}
99
+ ```
100
+
101
+ ```
102
+ match {$var}
103
+ when 1 {The value is one.}
104
+ when * {The value is not one.}
105
+ ```
106
+
107
+ - **Unknown Function errors** occur when an Expression includes
108
+ a reference to a function which cannot be resolved.
109
+
110
+ For example, attempting to format either of the following messages
111
+ must result in an Unknown Function error if done within a context that
112
+ does not provide for the function `:func` to be successfully resolved:
113
+
114
+ ```
115
+ {The value is {(horse) :func}.}
116
+ ```
117
+
118
+ ```
119
+ match {(horse) :func}
120
+ when 1 {The value is one.}
121
+ when * {The value is not one.}
122
+ ```
123
+
124
+ - **Selection errors** occur when message selection fails.
125
+
126
+ - **Selector errors** are failures in the matching of a key to a specific selector.
127
+
128
+ For example, attempting to format either of the following messages
129
+ might result in a Selector error if done within a context that
130
+ uses a `:plural` selector function which requires its input to be numeric:
131
+
132
+ ```
133
+ match {(horse) :plural}
134
+ when 1 {The value is one.}
135
+ when * {The value is not one.}
136
+ ```
137
+
138
+ ```
139
+ let $sel = {(horse) :plural}
140
+ match {$sel}
141
+ when 1 {The value is one.}
142
+ when * {The value is not one.}
143
+ ```
144
+
145
+ - **Formatting errors** occur during the formatting of a resolved value,
146
+ for example when encountering a value with an unsupported type
147
+ or an internally inconsistent set of options.
148
+
149
+ For example, attempting to format any of the following messages
150
+ might result in a Formatting error if done within a context that
151
+
152
+ 1. provides for the variable reference `$user` to resolve to
153
+ an object `{ name: 'Kat', id: 1234 }`,
154
+ 2. provides for the variable reference `$field` to resolve to
155
+ a string `'address'`, and
156
+ 3. uses a `:get` formatting function which requires its argument to be an object and
157
+ an option `field` to be provided with a string value,
158
+
159
+ ```
160
+ {Hello, {(horse) : get field=name}!}
161
+ ```
162
+
163
+ ```
164
+ {Hello, {$user : get }!}
165
+ ```
166
+
167
+ ```
168
+ let $id = {$user : get field=id}
169
+ {Hello, {$id : get field=name}!}
170
+ ```
171
+
172
+ ```
173
+ {Your {$field} is {$id : get field=$field}}
174
+ ```
175
+
176
+ Syntax and Data Model errors must be emitted as soon as possible.
177
+
178
+ During selection, an Expression handler must only emit Resolution and Selection errors.
179
+ During formatting, an Expression handler must only emit Resolution and Formatting errors.
180
+
181
+ In all cases, when encountering an error,
182
+ a message formatter must provide some representation of the message.
183
+ An informative error or errors must also be separately provided.
184
+ When a message contains more than one error,
185
+ or contains some error which leads to further errors,
186
+ an implementation which does not emit all of the errors
187
+ should prioritise Syntax and Data Model errors over others.
188
+
189
+ When an error occurs in the resolution of an Expression or Markup Option,
190
+ the Expression or Markup in question is processed as if the option were not defined.
191
+ This may allow for the fallback handling described below to be avoided,
192
+ though an error must still be emitted.
193
+
194
+ When an error occurs within a Selector,
195
+ the selector must not match any VariantKey other than the catch-all `*`
196
+ and a Resolution or Selector error is emitted.
197
+
198
+ ## Fallback String Representations
199
+
200
+ The formatted string representation of a message with a Syntax or Data Model error
201
+ is the concatenation of U+007B LEFT CURLY BRACKET `{`,
202
+ a fallback string,
203
+ and U+007D RIGHT CURLY BRACKET `}`.
204
+ If a fallback string is not defined,
205
+ the U+FFFD REPLACEMENT CHARACTER `�` character is used,
206
+ resulting in the string `{�}`.
207
+
208
+ When an error occurs in a Placeholder that is being formatted,
209
+ the fallback string representation of the Placeholder
210
+ always starts with U+007B LEFT CURLY BRACKET `{`
211
+ and ends with U+007D RIGHT CURLY BRACKET `}`.
212
+ Between the brackets, the following contents are used:
213
+
214
+ - Expression with Literal Operand: U+0028 LEFT PARENTHESIS `(`
215
+ followed by the value of the Literal,
216
+ and then by U+0029 RIGHT PARENTHESIS `)`
217
+
218
+ Examples: `{(horse)}`, `{(42)}`
219
+
220
+ - Expression with Variable Operand: U+0024 DOLLAR SIGN `$`
221
+ followed by the Variable Name of the Operand
222
+
223
+ Example: `{$user}`
224
+
225
+ - Expression with no Operand: U+003A COLON `:` followed by the Expression Name
226
+
227
+ Example: `{:platform}`
228
+
229
+ - Markup start: U+002B PLUS SIGN `+` followed by the MarkupStart Name
230
+
231
+ Example: `{+tag}`
232
+
233
+ - Markup end: U+002D HYPHEN-MINUS `-` followed by the MarkupEnd Name
234
+
235
+ Example: `{-tag}`
236
+
237
+ - Otherwise: The U+FFFD REPLACEMENT CHARACTER `�` character
238
+
239
+ Example: `{�}`
240
+
241
+ Option names and values are not included in the fallback string representations.
242
+
243
+ When an error occurs in an Expression with a Variable Operand
244
+ and the Variable refers to a local variable Declaration,
245
+ the fallback string is formatted based on the Expression of the Declaration,
246
+ rather than the Expression of the Placeholder.
247
+
248
+ For example, attempting to format either of the following messages within a context that
249
+ does not provide for the function `:func` to be successfully resolved:
250
+
251
+ ```
252
+ let $var = {(horse) : func }
253
+ {The value is {$var}.}
254
+ ```
255
+
256
+ ```
257
+ let $var = {(horse)}
258
+ {The value is {$var : func }.}
259
+ ```
260
+
261
+ would result in both cases with this formatted string representation:
262
+
263
+ ```
264
+ The value is {(horse)}.
265
+ ```
0 commit comments