Skip to content

Add option for array output#242

Merged
eemeli merged 1 commit intomasterfrom
array-output
Aug 31, 2019
Merged

Add option for array output#242
eemeli merged 1 commit intomasterfrom
array-output

Conversation

@eemeli
Copy link
Copy Markdown
Member

@eemeli eemeli commented Jun 30, 2019

Fixes #241

This adds a new method MessageFormat#setArrayOutput(), which makes compiled functions return arrays instead of strings, allowing for variable values to not be stringified. Some examples:

const mf = new MessageFormat('en').setArrayOutput()

mf.compile('simple message')()
// ['simple message']

const obj = { foo: 'bar' }
mf.compile('objectively, {obj} is an object')({ obj })
// ['objectively, ', obj, ' is an object']

mf.compile('select {num, plural, one{one} other{#}}')({ num: 42 })
// ['select ', [42]]

@eemeli eemeli requested a review from SlexAxton June 30, 2019 06:25
Copy link
Copy Markdown
Member

@SlexAxton SlexAxton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks simple enough. 👍

@eemeli
Copy link
Copy Markdown
Member Author

eemeli commented Jun 30, 2019

@FSchubert92 Would you be able to verify that this would solve your use case?

@rxaviers
Copy link
Copy Markdown
Contributor

rxaviers commented Jun 30, 2019

mf.compile('select {num, plural, one{one} other{#}}')({ num: 42 })
// ['select ', [42]]

Why ['select ', [42]] instead of ['select ', 42]? Note [42] vs 42.

Also, it could be useful to distinguish literal parts of the message vs variables... One approach is using an array of parts such as the one defined in Ecma-402 (ref). For example:

mf.compile('select {num, plural, one{one} other{#}}')({ num: 42 })
// [{ type: "literal", vaue: "select " }, { type: "variable", value: 42 }]

@rxaviers
Copy link
Copy Markdown
Contributor

rxaviers commented Jun 30, 2019

Another comment: MessageFormat#setArrayOutput() modifies the behavior of the compile returned function. Would it make sense to instead have another method for that sort of function, e.g., compileParts?

mf.compile('select {num, plural, one{one} other{#}}')({ num: 42 })
// "select 42"

mf.compileParts('select {num, plural, one{one} other{#}}')({ num: 42 })
// [{ type: "literal", vaue: "select " }, { type: "variable", value: 42 }]

@eemeli
Copy link
Copy Markdown
Member Author

eemeli commented Jun 30, 2019

Nested arrays: The runtime code is significantly simpler if the array isn't flattened for select cases. Now, admittedly for the given example the compiler could (and possibly should) skip the [wrapper], but it would still need to apply it for plural or select cases with a compound value. Also, as far as I can tell at least Vue and React don't really mind traversing a nested array.

formatToParts: Sure, that's another possibility, but is there an actual use case that should be considered for that? As is, at least React and probably other frameworks can use an array of values as is, but they couldn't use an array of { type, value } quite as directly.

compileParts: While working on this, I started to realise that the current ability to mutate and persist a MessageFormat instance across configuration changes is a bit clumsy. So I'm drafting another PR that'll enable using an options object as the second arg for the constructor, with an intent of later deprecating and eventually removing the current set/disable methods. This change is also meant to more clearly communicate that a MessageFormat instance is relatively light to construct, and that it'd be fine to build more than one if really needing to use different sets of options at the same time.

Btw, just to be clear, I'm happy to continue this conversation and even happier if the shape of this PR improves as a result. My starting point here is to find a decent way to allow variables to pass through without stringification, but if we get to solve other problems along the way, that's even better.

@FSchubert92
Copy link
Copy Markdown

@eemeli Yes, this option should fit our use case!

@erickwilder
Copy link
Copy Markdown
Contributor

My 0.02 cents:

This change is also meant to more clearly communicate that a MessageFormat instance is relatively light to construct, and that it'd be fine to build more than one if really needing to use different sets of options at the same time.

I would say this could be easily handled as a further iteration and given the limited context of this change (allowing vue-i18n interpolation with a custom formatter) this PR is definitely good as it is for now

@FSchubert92
Copy link
Copy Markdown

I just wanted to quickly ask whether there are some news on this issue?

@eemeli
Copy link
Copy Markdown
Member Author

eemeli commented Jul 31, 2019

This looks likely to become a part of the major release, of which I could probably package a beta/RC release within a week or so. Mostly because it'd be a bit silly to publish a new method just before removing such methods.

I'm still considering the exact API, to allow for the parts variant suggested by @rxaviers as a later addition without any breaking changes. Maybe something like this?

const mf = new MessageFormat('en', { returnType: 'values' })

Alternative naming suggestions are rather welcome. The default value of the option would almost certainly be 'string', and 'values' is the same as what this PR currently does, and later we might add 'parts'. Not sure if the shape of the output ought to be reflected here as well with something like 'flat-values', as [].flat() is surprisingly widely available already, though not by IE or Edge.

@eemeli
Copy link
Copy Markdown
Member Author

eemeli commented Aug 4, 2019

Rebased on current master and refactored API to match that suggested in previous comment.

@eemeli eemeli added this to the 3.0 milestone Aug 4, 2019
@eemeli eemeli merged commit 3e642f0 into master Aug 31, 2019
@eemeli eemeli deleted the array-output branch August 31, 2019 07:43
@oppianmatt
Copy link
Copy Markdown

thanks for adding this, I see it's in the beta branch. seems the typings for typescript was missed with regards to this option

erickwilder added a commit to erickwilder/vue-i18n that referenced this pull request Feb 12, 2020
Use the new `messageformat` interface[1] that changes the data type from compiled messageformat
functions to arrays, instead of the old behavior that converted everything to strings. The old
behaviour of `messageformat` could not be used without some string manipulation hack to make
component interpolation to work.

This also takes into consideration the simplified interpolation, slot-based interpolation, and
the _deprecated_ `place`/`places` interpolation styles.

**Other changes**

* Update dependencies; there was a bug in the vue-i18n version that prevented slot-based interpolation
  to correctly pass `values` to custom formatters.
* Update all vue-related dependencies to remove compromised packages reported by `npm audit`

[1]  messageformat/messageformat#242
erickwilder added a commit to erickwilder/vue-i18n that referenced this pull request Feb 12, 2020
Use the new `messageformat` interface[1] that changes the data type from compiled messageformat
functions to arrays, instead of the old behavior that converted everything to strings. The old
behaviour of `messageformat` could not be used without some string manipulation hack to make
component interpolation to work.

This also takes into consideration the simplified interpolation, slot-based interpolation, and
the _deprecated_ `place`/`places` interpolation styles.

**Other changes**

* Update dependencies; there was a bug in the vue-i18n version that prevented slot-based interpolation
  to correctly pass `values` to custom formatters.
* Update all vue-related dependencies to remove compromised packages reported by `npm audit`

[1]  messageformat/messageformat#242
erickwilder added a commit to erickwilder/vue-i18n that referenced this pull request Feb 12, 2020
Use the new `messageformat` interface[1] that changes the data type from compiled messageformat
functions to arrays, instead of the old behavior that converted everything to strings. The old
behaviour of `messageformat` could not be used without some string manipulation hack to make
component interpolation to work.

This also takes into consideration the simplified interpolation, slot-based interpolation, and
the _deprecated_ `place`/`places` interpolation styles.

**Other changes**

* Update dependencies; there was a bug in the vue-i18n version that prevented slot-based interpolation
  to correctly pass `values` to custom formatters.
* Update all vue-related dependencies to remove compromised packages reported by `npm audit`

[1]  messageformat/messageformat#242
kazupon pushed a commit to kazupon/vue-i18n that referenced this pull request Feb 14, 2020
* feat(examples/formatting): update custom formatter example

Use the new `messageformat` interface[1] that changes the data type from compiled messageformat
functions to arrays, instead of the old behavior that converted everything to strings. The old
behaviour of `messageformat` could not be used without some string manipulation hack to make
component interpolation to work.

This also takes into consideration the simplified interpolation, slot-based interpolation, and
the _deprecated_ `place`/`places` interpolation styles.

**Other changes**

* Update dependencies; there was a bug in the vue-i18n version that prevented slot-based interpolation
  to correctly pass `values` to custom formatters.
* Update all vue-related dependencies to remove compromised packages reported by `npm audit`

[1]  messageformat/messageformat#242

* fmt(examples/formatting): remove unused function param from custom formatter
etherdog-eth pushed a commit to etherdog-eth/vue-i18n that referenced this pull request May 31, 2021
* feat(examples/formatting): update custom formatter example

Use the new `messageformat` interface[1] that changes the data type from compiled messageformat
functions to arrays, instead of the old behavior that converted everything to strings. The old
behaviour of `messageformat` could not be used without some string manipulation hack to make
component interpolation to work.

This also takes into consideration the simplified interpolation, slot-based interpolation, and
the _deprecated_ `place`/`places` interpolation styles.

**Other changes**

* Update dependencies; there was a bug in the vue-i18n version that prevented slot-based interpolation
  to correctly pass `values` to custom formatters.
* Update all vue-related dependencies to remove compromised packages reported by `npm audit`

[1]  messageformat/messageformat#242

* fmt(examples/formatting): remove unused function param from custom formatter
wdavis122 added a commit to wdavis122/vue-i18n that referenced this pull request Jun 5, 2024
* feat(examples/formatting): update custom formatter example

Use the new `messageformat` interface[1] that changes the data type from compiled messageformat
functions to arrays, instead of the old behavior that converted everything to strings. The old
behaviour of `messageformat` could not be used without some string manipulation hack to make
component interpolation to work.

This also takes into consideration the simplified interpolation, slot-based interpolation, and
the _deprecated_ `place`/`places` interpolation styles.

**Other changes**

* Update dependencies; there was a bug in the vue-i18n version that prevented slot-based interpolation
  to correctly pass `values` to custom formatters.
* Update all vue-related dependencies to remove compromised packages reported by `npm audit`

[1]  messageformat/messageformat#242

* fmt(examples/formatting): remove unused function param from custom formatter
cooldev370 added a commit to cooldev370/jamesv that referenced this pull request Feb 18, 2025
* feat(examples/formatting): update custom formatter example

Use the new `messageformat` interface[1] that changes the data type from compiled messageformat
functions to arrays, instead of the old behavior that converted everything to strings. The old
behaviour of `messageformat` could not be used without some string manipulation hack to make
component interpolation to work.

This also takes into consideration the simplified interpolation, slot-based interpolation, and
the _deprecated_ `place`/`places` interpolation styles.

**Other changes**

* Update dependencies; there was a bug in the vue-i18n version that prevented slot-based interpolation
  to correctly pass `values` to custom formatters.
* Update all vue-related dependencies to remove compromised packages reported by `npm audit`

[1]  messageformat/messageformat#242

* fmt(examples/formatting): remove unused function param from custom formatter
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Problem with Component Interpolation and V18n

6 participants