Skip to content

Latest commit

 

History

History
516 lines (263 loc) · 45.8 KB

10-25.md

File metadata and controls

516 lines (263 loc) · 45.8 KB

October 25, 2023 Incubator Call Notes

Attendees:

  • Eemeli Aro (EAO)
  • Ujjwal Sharma (USA)
  • Bradford Smith (BSH)
  • Jordan Harband (JHD)
  • Shane Carr (SFC)
  • Richard Gibson (RGN)

Intl.MessageFormat

Summary/Conclusions

Error handling: Let’s keep the current API, with warning by default and including an onError formatting call argument. Providing a best-effort API is in line with the general approach used by Intl. For fallback values, ensure that they are not customizable by an error thrown by a MessageFunction.

MessageFunction API: Keep the current API with valueOf and options, but remove anything that looks like encouragement to use new Number() as a MessageValue even if that does happen to work.

Notes

Note that below is a Google Meet transcription, not hand-written notes.

EAO: Hi and welcome, everyone.

EAO: The agenda has effectively two items that were raised specifically during the last TC39 meeting. There's plenty more in the API to go into further, but getting some development or ideas on these would certainly be beneficial. So the first one is error handling which is a little bit weird here. And then the second one is about the potential complexity in the API for custom formatting functions and how do they need to work? I don't have any slides specifically prepared for this but if you guys want I'll be happy to step through the relevant bits from my presentation in Tokyo. Should I do that or do you feel so comfortable with all of this that you'd like to just jump into all of it?

JHD: The review is probably helpful. It's been a few weeks.

EAO: So for a very very quick overview. The overall API we have has an Intl.MessageFormat object with a Constructor. And then the formatted format to pause calls and then when you get deeper into it, the options may include a mapping of named message functions, which have a signature specified here. The specific things to consider here is what's happening with the functionality for when formatting fails. This was highlighted as a question that this API is doing differently than what we tend to do in Intl calls.

EAO: The default action for when we have a message that we're formatting and something fails in that formatting and we're not talking here about a syntax error because the Constructor call will fail if the syntax of the source message is broken. If the syntax is fine, but we have for example a custom formatting function that is used in a message and that itself throws an error due to whatever reason bad in folks bad code, whatever reason then the format and format to particles they don't throw an error by default, but they emit a warning which is what the proposal currently says and then that behavior may be customized by a on-air argument on the API calls. So this is one whole thing for us to consider here and the other one is that

EAO: so this is one of the few examples I have for how do you use this API? And this is So we're iterating on the syntax still because Never mind, the specifics of the syntax, but we can have these variant patterns in a message which depend on some values such as a number on which we're doing plural selection here. and The number function there is one of the ones that we are kind of defining by default to be something that ends up calling the Intel DOT number format into rules set functionality. But it's entirely possible for users to Define their own functions to use within message format and that then means that we need to find ways of having that work for them because We have both the format and the format to Parts calls and these custom formatted Yeah.

JHD: Can I even go back to that code example real quick is maybe I'm very unaware of the message formatting thing you're going with this,…

EAO: Let's see.

JHD: what I was envisioning was something that's for printf or console.log, where you have markers, and they get interpolated, and then you can choose to apply transformations before it producing the string but that looks like a whole DSL is that by default part of message format?

EAO: Yeah. a big part of localization is being able to deal with variants like this.

JHD: Wow, okay.

JHD: I get that, I and I maintain one of airbnb’s libraries called polyglot, and it has a sort of infix notation to handle all the various pluralizations options, so I get the need for it. This just seems like a very complex DSL that I was just unaware of and it's surprising.

EAO: provide

USA: Maybe that's because still being worked out at the moment. It's part of the

EAO: the fundamental structure is still going to be there that the complexity is still going to be there whether it's presented how exactly it's presented is gonna possibly vary but one key aspect is that the concept of plurals for instance is not baked into message from a 2 at all that is coming from For example a number or…

JHD: Okay.

EAO: a plural function if we end up there's a small discuss some amount of discussion on that.

JHD: the concept of how many plural rules there are - that's language specific and I like that I'm hearing that that's not part of this, but you have when zero when one star like that to me seems like something that's designed to have plural rules for zero one and two plus which many languages do. Not all of them, but that's okay, because you typed out that input string. I mean I am confused about spelling out the word one and not the word zero and so on but that's bikeshedding stuff that's less important - is this whole structure already something that's used in the ecosystem or in Intl?

EAO: Yeah, something very much like this. So for example ICU message format has three different selectors that it offers. It is plural ordinal number selection and then a catchable select where is just matching strings to keys that are string equivalent.

JHD: okay, so there's not much. if I have comments about this DSL structure that's largely already a settled thing or at least it's being worked out in another body and

EAO: Yes, all of these syntax within method format to is being discussed within the Unicode consortiums the message for my working group, which is under the CLD RTC. and…

JHD: okay.

EAO: that is a separate conversation from what we need to deal with…

JHD: Right, right. So for example,…

EAO: which is around the API.

JHD: if I said that should be the number one and not the word one you could take that feedback back to them. But that's where we're effectively delegating the decision-making about how this structure works to them.

BSH: but

EAO: Yes.

JHD: we're just talking about the JavaScript API once that's parsed.

EAO: Yes.

JHD: Thank you. That's clear.

EAO: But yeah.

JHD: okay, carry on

EAO: the custom formators question was one that was also raised and it's on the agenda as the second item. Is to consider that?

EAO: Okay here it's referring to the image function here as we have a message here that have a cow effectively is the message but the cow is an image and colon image is not something that we baking into the language at all. But in this case, we're considering that someone has provided an implementation of an image function that ends up resolving ultimately and Don element And to be clear, this is not the source. Of It is the image Dom element that is resolving to and the question then becomes.

EAO: is this the sort of functionality that could theoretically be left out of an MVP sort of a solution or is it so deeply baked into how message from a two works and what we want to be able to do with it that it needs to be accounted for and if it needs to be accounted for how do we resolve all the issues of what's possible within the message from our two syntax to happen with that value such as what do you get when you Call an image. and then how do you deal with it? And this then is currently the result by having a message function

EAO: Being a user definable function that can be passed in the options which takes in a source expression. basically it should be treated is a blob identifier for it and the preferred local and it's fallbacks. And then a bag of options that may be passed into the function call such as here the alt equals cow. That's an option that is passed to the image function where it counter PNG is a string positional argument. That is a password as the input.

JHD: so I have a question here.

EAO: Yes, go.

JHD: If you go back to the input string.

JHD: In that input string if you look at we don't have to switch back to it. But the previous one that I had asked you to show me the end all the input strings there. It's pretty straightforward to me to highlight which parts are translatable, to give to translators.

EAO: Yes.

JHD: but in this case the word cow in the alt needs to be translated, but none of the other text inside those inner curly braces may be translated. So when you're writing this string, how do you call out that the alt value is translatable and the rest isn't?

EAO: The message from up to solution to this is that in addition to specifying the syntax Financial trauma 2 we're specifying in that working group a whole bunch of other stuff as well. One of the assets that we're defining is a sort of a function interface registry. Which is it? It's gonna include by default something like a definition of what sorts of options does a colon number function take it? and the other sort of functions that are provided by default and…

JHD: Okay.

EAO: the intent is that it becomes possible for an Implement of the image function to also extend this sort of a function registry and Define their not just that for example the alt

EAO: That alt is a valid option but option name, but that takes maybe a string but also to find that that is a localizable attribute and…

JHD: Localizable is the better word, thanks.

EAO: this information but can then be taken into account either by the translation management system that's directly working with this or if we transforming the message from our two representation of this message into a form that is handled by a translation management system to have that account out of this

JHD: Okay that answers my question. But sort of adds a new one in the sense of you sort of implied a stateful registry and I think that's something that we desperately wouldn't want and I would hope that languages in general wouldn't want them.

EAO: It not necessarily stateful but more like there's a base layer of the registry and this registry may be extended by implementation.

JHD: per message format instance in this API for example?.

EAO: if need be yeah, but I mean some is it the expectation is that not every single application is going to Define their own functions,…

JHD: Okay, cool. Got it.

EAO: but that they're going to be for example relying on libraries of functions or others that are going to be Doing this sort of work Bradford. Did you have your hand up earlier or was that?

BSH: I did but I put it down because I think you answered it.

EAO: Okay. Yeah.

BSH: Ujjwal had his hand up now.

BSH: So to summarize to put in mind words effectively the alt equals cow here. It's up to the function that is being called to know that it needs to translate cow and to figure out how to get that done.

EAO: no, so we a lot happens with messages. So we have what happens during runtime. This is what's showing on the screen here is what's happening during the runtime when we're in JavaScript. We wanting to format a message and it includes a cow. that is something we explicitly need to Define effectively within this Intel Dot message for my proposal. But then separately from this how do you get the English have a cow message for instance? to be translated in a completely different language and those transforms that get the source have a cow message to a translator and have them be able to do that work and get that work back into the shape that we can use it with this interface.

EAO: Those are beyond the scope of the Intel method format proposal. But those are within the scope of what needs to be considered within the message from our working group, which is considering this as well.

BSH: Let me see if I can rephrase this in terms that.

BSH: we use messages like this already in Google and We basically have a process where the closure compiler knows about such messages and expects to see them in certain ways in the code. And so there's a special. Program basically that's based on closure compiler that will run over your code find all of extract the messages themselves to put them in exit xmb format, and then that's what gets sent to translators. And then they created an xtb format, which is for a specific language which then when we actually compiled this into running code we use that to do the appropriate replacements.

BSH: It sounds to me like what It's at the extraction time where you're pulling out all the messages that you have to recognize that. this alt Eagle's thing cow is one of the things that needs to be translated. And so that needs to be somehow called out.

EAO: Somewhere along that path. Yes so you can have a runtime implementation of the image function and you can use it during the runtime. But in order to be able icate to translate those somehow that the alt option here specifically is translatable that information needs to come from somewhere. And in the message from my working.

JHD: The image author needs to have a way to declare it that could be consumed by the extraction process and it's not part of JavaScript to figure out what that is.

EAO: Effectively. Yes.

JHD: that makes sense to me.

BSH: Let me get another clarification if I could to make sure that the way things are working for us now is similar at least to what would so again today with today's version of the ICU message format. What happens when the compiler after we've done the extraction and we send it to the translators what they might send back is say that's why Heely translation of this and so we would basically have instead of have it be whatever the Swahili version is count up. PNG would be unchanged alt equals would be something different than cal probably and then what we actually would end up spitting out as the final JavaScript would be

BSH: That this string. So at runtime it would be an already translated string that's getting passed into message format that is still the intention of how this works. It's not the format does not somehow magically know all the translations for all the locales and…

EAO: Yes.

BSH: then picks between them. You still actually giving it the actual language text when you talk call it,…

EAO: Yes.

BSH: Okay. Thank you.

EAO: We unfortunately do not have sufficient magic to do what you're asking for. It would be really great though.

BSH: yeah, it would be kind I could totally understand why I just want to make sure I thought maybe you figured out some magic that I didn't think of yet. So.

EAO: But yeah, so the issue that specifically on the agenda. Here is the implementation of this image function. It gets a little bit complicated because we're not just formatting to a string here. For instance. we're eventually, formatting to a Dom element. And that does the DSL aspect as Jordan you refer to of let me see if I have an example.

EAO: Sorry.

EAO: Okay, so it's not quite the same but here in addition to the input statement another statement that is available in message from up to his local which creates a local variable to this message. and that value can then be used elsewhere and here for example, we could conceitably have something like

EAO: And operation that happens. on

EAO: on the cult value and this means that we need to account for this possibility as well in how are we handling? how a custom user-defined function works? How do we make this sort of thing be at least possible to be done with something like colon image?

EAO: so the current solution to this is that the message function that is defining the image function or the number function returns a message value, which is an object which has a set of fields on it. And the presence or absence of some of the fields here are defining. Where they can be used as a selective, for example. As you saw the early example where the key Parts formatting to a string. and then

EAO: where they can be used as a value passed in as an argument as an option value of another function all still within message format. And we'll call that there's the options and the value of Parts here because this is then. Linking up to not just wanting to actually be able to have custom formators. It's the concern that we ought to be able to support.

EAO: compound value which for example a number together with the currency attached to this because how do you format? This is of course local dependent and we need to get these to be able to come in and hopefully as a one thing so you can have a one thing that's saying 42 Euros rather than having separately 42 and Euros, which might get lost in the way having the currency. Itself be something that a translator might end up accidentally localizing I don't know. From dollars to Euros or Yen anything else? So it gets kind of complicated and this is why there is this.

EAO: Range and complexity in what a message value for instance here. Looks like which one?

USA: I have a doubt in the API design in the last slide that you were on. instead of passing The currency is one of the options. in the message you rather attach the currency to the number instance and then as that in is that how it's supposed to work or

EAO: This is a proposed way for this to work. Yes. Because we are ultimately from a certain point of view will a localizing one thing and that what a thing is It could be 42 kilometers or…

USA: right

EAO: there's still these sort of paired things…

USA: yeah.

EAO: where we know we have a number and the units for it.

USA: totally that

JHD: It seems like it would be better to have a value: 42 rather than encouraging boxed primitives, though.

JHD: instead of saying this is a boxed primitive with expandos attached we'd say, we're just gonna have an object describing everything about it including the content.

EAO: So rather than having something like depending as this is effectively what the proposed text in The Proposal is doing is depending on valueOf returning a number. So you're saying that it might be better to have a value? and that an options value all as a

JHD: It's fine if that happens to work. But that shouldn't be what people reach for

BSH: Ideally, there should be a custom kind of object rather than trying to take a number and stick an unusual property on it.

JHD: right

BSH: That's kind of weird and likely to cause problems somewhere down the road.

USA: yeah, but

BSH: It'd be better to have a specific kind of object that you create for this case that has a value which is a number and also has other properties.

JHD: so for example that thing that I just pasted in the chat has the same API to in some ways as this example on the slide, but it doesn't encourage use of boxed primitives. So I'm not objecting in any way to what that's on the slide being a thing that happens to work, but it shouldn't be the way people try to write it, or the way we explain it. So this is fine if what you have on here falls out of the design semantics, but the design semantics should be based on what I pasted not around the example on the slide.

EAO: So to me. this overall question is maybe something ujjwal and Shane you might be able to comment on is that if we create a way to Express a compound object like this. Let's say a number with currency or a number with units or there might be a couple of others. Should these sorts of compound objects that are a formattable at least via message format? also for example by Intl.NumberFormat.

USA: That's actually where I was coming from initially. NumberFormat has this API where it takes in the number of value and then everything else is part of the options. So here you have the style option and then instead of passing the currency in the options. You pass it down sort of attached to the input value. So it's sort of a different style. There's no reason why this shouldn't work, but it's a different approach to How the number of format?

JHD: And I mean I get why you would get here, Because the API Ujjwal is describing takes one value. And this one is taking a dictionary - so it makes sense not to require two parallel dictionaries and to instead require one dictionary where the key somehow encapsulates the value and the options, right?

JHD: So I don't think that there's an issue with consolidating it into one dictionary. I'm just talking about what the right hand side's values are of that dictionary.

EAO: Shane

SFC: It looks like you're having to merge the options together because you have style currency. In the message string,…

EAO: yes.

SFC: So that's one. I'll give me how to specify the other is it seems a little weird maybe I guess JavaScript let you do it to set the options on the number objects. I would think more maybe typescript friendly way to do it with this What would be to have a protocol where as an object with the value field is the value and everything and then the options field is the options.

EAO: This is exactly the sort of question. Yeah, I would be happy to iterate this API in that sort of a Direction. just showing that I literally had this question On the slides I presented in Tokyo, but there was a lot there. and so the one question that I would be interested in getting clarification on going forward with something like this is whether to see to formulate whatever this tells into to be something that is specific to Intel Dot message format or whether to formulated as a change on Intel DOT number format that may then be used by message format.

EAO: I think Shane that's a question to you.

SFC: I don't totally understand the question.

EAO: So in MessageFormat, we have a use case for having a compound value that can be formatted as a number somehow combining or giving an option value like a currency together with a number. Bradford mentioned earlier the possibility of creating a new object specifically for this and having that kind of just work like a concrete MessageValue instance, or it could be just a defined that if the input is an object and it has a value field that has a number and it has an options field that is a map of options then do all of these things. My question then is that as I iterate on this. Should I be iterating on this compound value to work specifically and only on MessageFormat calls or if I can call Intl.NumberFormat with this value?

SFC: You can't call Intl.NumberFormat with it because you're mixing The Constructor with the format function because most of these things go to the Constructor whereas Only the number of value goes to the format function.

EAO: Good point. Thank you. Cool, excellent further question on this. Would it be better to create something like an Intl.MessageValue Constructor and a specific reified object or should it just be a well-defined structure that an object might have?

JHD: To make a reified MessageValue thing is very OOP and Java-like, and so I get the impulse to do that, but it's probably better to stick with plain objects unless there's complex behavior. if we stick with plain objects, and then that plain object ends up needing complex validations or behavior in multiple locations, then that speaks to the need and tells us we should have made it a first class thing. But if in fact it's just encapsulating data in a schema… I mean iteration results aren't a class, they're just an object, and so I think that fits more with the language to just use plain objects.

USA: I mean Yes,…

EAO: Does everyone agree?

USA: I was going to say within the spec at least there is a way to do that by just specifying what say MessageValue records look like so it's just a graphite interface. And then we can obviously document that on the MD inside.

EAO: This is entirely happy to start making that change as a follow-on step from here. And as mentioned here. It actually ends up effectively answering the two questions I have here. because if we're turning valueOf into value having options remain…

JHD: I think that's actually a separate question because that question is should it be a value or should it be a thunk (a function that returns a value)? The reason to make it be a function is because then if it's expensive to compute you can defer its computation and that applies regardless.

SFC: A value getter could also be lazy computed but I kind of like,…

JHD: I mean, that's true, but…

SFC: I mean, it's very JavaScript So to write valueOf and I'm kind of generally in favor of that kind of style but it seemed like this is the opposite…

SFC: though of where we were, Kevin Gibson's has been giving those presentation about implicit conversions and that seems to be something that the community doesn't really like.

JHD: But that's the thing is if that's why I reacted that's part of why I reacted so strongly to that new Number slide, but just because it's so happens that that would work is not so big a deal because the spec here would be doing Invoke on it, and so it's not implicit coercion because it's not doing ToNumber or ToString. it's not even coercion at all - it's not going to change the type of the return value if it's an object or if it spits out a symbol, it just so happens that the function name matches the protocol. Obviously if that's an issue and the explicit laziness is still desirable, then we can just come up with a different name. But I also like the cleanliness of valueOf and I don't think it runs afoul of Kevin's presentation.

SFC: Okay, great.

BSH: Here's what I'm thinking about to make sure I'm on the same page. The main question I think that we're talking about right now should be the way you get the value from one of these objects be calling a function or just accessing property and I'm gonna make this argument for it being a function. The way in the formats work is that there are multiple alternatives. And it could be that you might not actually need the value. You might not need it. You might go to format the thing and then it turns out we don't actually need this value because the case that we're looking at is one of the cases that doesn't use it. And since that is the case, you might not need it I would argue for it being a function that way if you never actually need to get the value you don't do whatever computation is necessary to get the value at all. Otherwise, you always have to compute this value and always have to pass it in. It has to be computed before you call the message format.

BSH: And that's not as good. that's inefficient.

EAO: So while I agree with that, I'm very happy to keep the valueOf would like to point out that. When looking at real world messages, a vast majority of them don't include any sort of values, and the ones that do are really simple strings. Then a subset of those that end up having multiple variants from which to choose and a vast majority of those are going to be using the same values. so if you have it on One path, you'll likely to have it on all the paths. So it is true that there is a subset of all messages for which the valueOf being a function would allow not being called and saving some efficiency in there, but the overall saving in terms of processing time that this gains us is relatively Limited.

EAO: Just thought I'd mention that but happy to keep it as valueOf.

JHD: so I don't know if any of you are in the JSX matrix channel, but Dan made a comment the other day that was basically one thing he doesn't like about JSX is that the values are directly stored and not thunkified. I haven't replied yet because my initial reaction was “but in practice that doesn't matter to anybody” but if for those it doesn't matter to tacking on () => is a minor cost especially since it's done in the transform code, but for those that it matters to it's like a showstopper. I'm still deciding my opinion on that for jsx, but it has informed my thoughts here a little bit that it might be better to design with that in mind, because we could always later add a value that's mutually exclusive with valueOf so you can choose your flavor, but I would rather start with the more capable one than the more ergonomic one especially given that this is going to be rarely used - that sort of suggests that ergonomics isn't what's important, capability is.

EAO: Okay, then I have a follow-on question from there, which is actually on the slide there. So if we are going with valueOf as a function to get the value, there is the options part that is not just a single value but containing argument pairs like the alt=Cow. Should that also be expressed as as a resolvedOptions function or should it be just directly the options values as expressed here.

JHD: What's the difference?

EAO: Is it like the valueOf function or is it directly options?

JHD: but the options are resolved unconditionally?

EAO: It's the same boat that they're coming in at the same time.

JHD: I see.

BSH: The problem is the example you gave was just alt=Cow, which is obviously fully resolved.

JHD: right right

BSH: How would you have a case where it's not? What would it look like to have a case? That's not fully resolved to start with?

EAO: For example, the alt could be coming from a variable that needs to be given externally and then looked up to get its value?

EAO: But it's very much the same sorts of argument as for the value. One way of looking at it is that the value is a positional argument whereas the options are a bag of named arguments.

USA: I feel like the way MessageValues are used, it's not obvious if options can be replaced by resolved options because in the case of Intl Constructors, we return resolvedOptions after they've been resolved but MessageValue is also being accepted as input. To pass in something called resolvedOptions would be weird.

BSH: Or is it your expectation that the fields in this options object that you get with themselves be MessageValues. And so if we're using valueOf they're sort of already a delayed sort of thing and you don't need the additional layer.

EAO: They may be in some situations. Yes, so it gets convoluted the deeper you go. But yeah, if you add those layers then the valueOf is providing indirection already.

USA: So personally I like options here then because that refrains from making any qualifications to the options.

JHD: I feel like options generally aren't things that are expensive but values can be

EAO: I would be happy for the API to effectively communicate this as well by implication. I think the cost of needing to always have those options even if the value is never used Is likely to be much less than the potential cost of what a Computing a value might be but even then my presumption is that the cost of computing those values is going to be relatively low.

JHD: I would say that as well as with both of these even if it's just a property. You can always make it a getter and make it lazy but the ergonomics and performance of that are horrific. So there's always that escape hatch even for options. So it's more like do we think that it's an important enough capability to make clear in the API? And that decision can be different between value and options. I can't conceive of a realistic use case in any API where options are expensive whereas value I can conceive of many use cases, even though they don't happen very often.

BSH: For one other question about that. I think I want to make sure I'm clear on this you said that you expect that for someone who's defining their own function that they would need to somehow communicate to a registry somewhere to Hey, I have an option alt and I expect that the value given to that is going to be a string or I have an option food and I expect the value that's going to be given to that is going to be a combination of string of number and currency. Is that a thing that is that part of this design? Or are you expecting that Basically? All of the options are going to be broad numbers and strings directly past?

EAO: I am not making such assumptions. I think that's gonna be the case in most situations, but not in all by any means the important part here is to consider Who are the Readers or listeners of the registry and here on one part. There's the tooling. and that goes and commute makes the message translatable for translators and also can possibly handle it on the way back and the second utility there is validators that can look at a message and say hey, hang on you put a wrong thing here. That's a bug please fix or they can check that if a translator. doesn't incorrect translation, it might be able to catch not all but some mistakes that are made and that sort of a level and the third consumer of something like a registry are syntax highlighters and other developer tooling DX sort of things so when writing a message you can Have Auto completion and other things working.

BSH: Part of what I'm asking is the registry we're talking about here primarily a compiled time slash Tool Time existing thing or is there some existing registry that could change the behavior at runtime is it both or is it only for this is a registry you use when interpreting these messages with tools to extract messages and put things back in but it's not a runtime thing that is there in the JavaScript when the JavaScript runs. So not a runtime thing at all.

EAO: Tool time thing. In the runtime you need to actually implementations of the functions, but not a definition of their interfaces.

BSH: Okay, thank you.

EAO: I would briefly like to go to the first topic of the agenda, the error handling and have a brief discussion on that. Very happy about this. This is informed. A lot of the message value and I'm happy that what we've ended up with on this part at least has said, I should not change anything in the actual implementation just change how it's been presented so I don't show a new number there.

JHD: Yes.

EAO: but then there's this part

EAO: so because we've got so much going on because effectively unlike the other Intel format we are relying on provided data. and we were expecting to present this to a user the Practical reality is that sometimes this is going to fail that messages connects are gonna expect to have a value a variable, passed into them to fill a placeholder and a user call is not going to include this

EAO: at one version of a message has been translated under the message has been updated. But now we're using the old localization for Urdu and he doesn't do a thing that we expected to do and it's wrong. And what do we do in this situation is that many of the current systems that exist will fail and you're gonna throw an error and this ends up being a really bad experience from a localization point of view. Are you export of you where we might have the Otherwise perfect. But one single button text for instance the method formatting for that has failed.

EAO: if we throw an error in format to parts, this is going to lead to that sort of an experience. for many people

JHD: wait wouldn't that prevent that experience because if you throw an error then the whole page fails instead of it silently continuing with one button on translated wrong?

EAO: yeah.

JHD: If you don't throw an error, then you're risking an unexpected state in the words on the page.

EAO: Yes, and the argument here is that in general. I fully agree with you that throwing the error and showing a blank page. Is a right thing to do. but with intel.messoformat in particular in many cases the distance between…

JHD: Okay.

EAO: where a developer is going to be working on the messages and testing them and when they actually end up being in the wrong time going through translation transforms there on the way back again is going to mean the stuff is going to fail during runtime for localization more often than otherwise And given this and given that many of these error situations that will be experienced or effectively not testable. because in order to be Not testable completely ahead of time.

EAO: It is a better default Emit a warning and for the format to Parts calls by default. Not to fail but to return string some decent message representation. Shane

SFC: This is fairly consistent with how other Intel apis behave they make a best effort. Because there's a lot of different environments. And especially into a message from it for the reasons MLA just describes.

SFC: Yeah, I think having data driven exceptions. This is not the right place to have exceptions. if things are very easily testable. I sort of like the way that Emily put it there then we should lean in that way. But when we can have a reasonable fallback Behavior we should

EAO: Bradford

BSH: Still trying to show the rest of the web page because you don't want to and so this is more of that nature, but the corollary is if that's what you're going to do. That means that you need to require the user created functions to provide some sort of fall back Behavior, So that if the functions given something it doesn't understand. it's guaranteed to have a Hopefully human readable fallback.

EAO: This is in part addressed by a message format syntax itself, which defines in this formatting specification how to deal with the fallback. And for example

EAO: Yes. Yes.

EAO: This is all specified already Jordan.

JHD: When you say specified in this proposal or in ICU?

EAO: in the ICU proposal for message format 2

JHD: what you showed me with the image example there's some external metadata that says hey, I'm the image function. This is the schema of my inputs and blah cool at runtime. It just calls that function and passes alt: cow and the src or whatever - that all seems straightforward to me. Where does the runtime fallback come from here? Is it in the Constructor for message format somewhere?

EAO:

EAO: No, so for example taking this if I understand the question, right, first of…

JHD: Yeah.

EAO: if we end up passing an invalid bad source to the method format Constructor, then we're going to throw from The Constructor. I mean It yeah.

JHD: Yeah, I'm talking about it's syntactically valid, but during the format call it throws.

EAO: Yes, for example in this case. The image function itself could throw. And that scroll is caught by default by the message format runtime,…

EAO: which will then consider this whole expression to have failed and specifically in this case. It's going to emit a fallback part that's going to include the cow.png value that is given to this function and then Sorry, the format to string is going to if I remember I'd have curly braces and vertical bars around the counter PNG. Whereas the format two parts is going to have a type fall back part that is going to be included in the output.

JHD: okay, I mean so given that it sounds like the word cow should be the first item and instead of the alt being an option the src should be an option because you'd rather it say “have a cow” then “have a cow.png” but that would be all the choice of the author of the image function. I'm guessing.

EAO: I can't remember but it might be included in the proposal. Honestly. I've worked on it so much in different variants the error that is thrown from the image function May Define its own fallback to use for this…

JHD: Okay.

EAO: but Did they? Show the error thrown by the image. function may say that the default back to use for me given that I failed is this value here rather than the

JHD: Great.

JHD: okay. an error carrying information that is a big thing that isn't done currently so If that isn't.

EAO: I can't remember if I included.

EAO: So that would be a no let's not have that.

JHD: to me that would tip the balance of custom functions should be a follow-up.

JHD: because it's already borderline in a lot of ways of whether it should be included in this or just done as a follow-up and coming up with a way for errors to communicate reliable information is like a big proposal that potentially could affect many things that aren't just Intl.

EAO: Okay.

EAO: Getting the feedback to don't do a thing. I'm very happy on this level to take cool

JHD: I mean so would in your L example, that's sort of what I mean by your HTML example as the content of the unknown tag is supposed to be the fallback value. so that when it fails that's what you see and if the image fails to load it's better to show them the alt then it is to show which is what browsers do then to show them the source, but thanks everyone. But yeah, but this is again I'm taking issue now With the example again based on my newer understanding of what the thing is doing. So given that if you're gonna make that argument, which is a decent one that it's like HTML and it just should be best effort like the rest of it. So that's a solid argument. Then I would hope that the examples should match such that it should very obvious to see for me to see if that function is just written as throw no and that's the entire content of the function. Then I should be able to look at the message input and figure out roughly how it's going to fall back and it should make sense to me from a ux perspective. And then that makes it a compelling example.

JHD: then

EAO: This is hopefully I've not written up any of this in the proposal. I can't remember if I have But yeah.

JHD: Yeah, no, it's I mean,…

JHD: yeah, and then to your other comment about the fallback values,…

EAO: If it's there,…

EAO: I'll take it out.

JHD: I do think that in UI I have seen a lot more problems caused by partially completed uis that were best effort. Then I have by. no. It's an error like we're working on it. And then not letting them continue. So it may be application specific but I would probably always Define my air as throw error. and…

EAO: Yeah.

JHD: nothing else

EAO: this is why.

JHD: and that's including in my past lives working at Airbnb or coinbase or something. we would always want the page to fail unless it was perfect.

EAO: And that is entirely a valid thing for a user and this API is intended to allow for this but it's intended for the default behavior to not be catastrophic.

JHD: right

EAO: But yeah.

JHD: Yeah, we can talk about it another time…

EAO: and on that I mean

JHD: since we're out of time. But I feel like the browsers may have worked out better had they chosen to be default catastrophic in a lot of places.

EAO: Yeah.

EAO: I think they may have been some historical conversational that previously. visual

JHD: I'm sure.

USA: I mean, I see your point Jordan, but I think due to the additional sort of Intel variables here. I do feel that it's sort of Changes my own mental model a bit,…

USA: right? I feel like there's really so many odd things. in the localization area which could make you have a slightly less than perfect output, but Something that works in the traditional sense of the word, but not perfect so that way you could both return an error while you…

USA: returning what your best effort localization was and then obviously the user can decide what to do with that.

EAO: so is the API for the onError here acceptable or is there a different API for both returning a value and allowing for? Error to error Behavior to be configurable something. So can I leave it like this or is this something about this that I should change? This is the best

JHD: I think leave it like that until you have a better option. I mean the proposals early enough that that's fine. I'll certainly try and think of one.

EAO: that

JHD: I hear what you're saying is and like I said the “Intl best effort” combined with “this is what browsers do” argument is compelling. It is a convincing argument somewhat - it doesn't immediately make my decision, but it's a strong argument and I'll have to think about it. and if the like because the only suggestion I've got right now is just remove onError entirely and throw always but it's been explained that might not be what you want all the time and my earlier argument 20 minutes ago was capability over ergonomics for things that aren't common.

EAO: and the thing Jordan is that if we throw like that rather than returning and they would be a really strong case to be made to have a representation of the message be attached to that error object that we throw. so that the one the

JHD: It can be with .cause as long as the built-ins don't read it, it's fine if users code reads it - there's nothing wrong with throwing something descriptive in the .cause, it's just the builtin shouldn't be trying to read that and respond to it.

EAO: yeah. Okay.

EAO: cool But I'm going to leave it as is for now.

USA: it's

EAO: bourge one

JHD: Yeah, that's fine.

USA: Yeah, somebody who's also been in this journey of coming to terms with this exact Behavior. I would say that if the catastrophic just throw the error. is not a viable solution here. Then I think of all the ways you could design API this field the most JavaScript team is supposed to why the more go thing where you return a ordered array of value comma error

EAO: It introducing that to JavaSript would be interesting.

JHD: yeah, no, No, I agree with you completely as well. this is the most Javascripty way. It's just not the most ECMA-262-y way so that's part of my eyebrow raising, but I don't have a better suggestion yet.

USA: No.

EAO: Yeah.

EAO: Thank I think we're about 10 minutes over time. We managed to actually cover the items on the agenda. Even if in reverse order. and to some extent thank you very much for your participation. One question. Is that should I attempt to schedule another one of these for some time right there? Are you guys interested in iterating further on aspects of this API or should process from here on just be async and we figure out another incubator call if specific needs arises.

JHD: Incubator calls are high touch, so it seems like let's just go async and then if there's further questions I'm happy to have another call.

BSH: And I think it's fine. I should make sure that I'm subscribed to the repo on GitHub. So I'll see when you post up there. But yeah.

EAO: Thank you. I'll hopefully get the transcript stuff somehow from Google and I'll add that to the notes then ping all of you probably in the reflector when I get that updated and then after some while update the notes to the incubator-agendas repository and I'll make an update to drop the “new Number()” from the proposal itself. Thank you very much.

JHD: Cool, okay. Thanks, everyone.

USA: Thank you.

Meeting ended after 01:05:43 👋