-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
select
/boolean
and unions
#102
Comments
Before I forget my idea was that potentially output could look something like: // Now
{ x: string; y: number }
// After
{ x: string } & { y: number } This continues to offload everything to tsc and in theory makes it easy to branch at any point with a union: { alwaysProp: string } & ({ type: 'email' } | { type: 'service'; serviceName: string }) |
Perhaps we could add a special case to
In the generated TS, the param |
That's interesting. I suppose it'd be analagous to Ideally though a syntactic construct for If we say hypothetically the implementation would be doable, how about this?:
Or a motivating example for the broader
|
Interesting. I guess this means further deviating from the ICU spec, but otherwise I think this looks good! With regards to the ICU spec, do we need to be concerned about confusing translators with syntax they haven't seen before? Or perhaps this isn't an issue because I don't think the translators (in our case) deal with the raw ICU—they have a tool that parses the ICU message and displays it in a special UI. |
Thinking about this more, I think there are two separate problems described in the OP, each requiring their own solution. Should we split this up? |
This'd break virtually all the TS tests, but here's roughly what a passing test with this feature would look like: diff --git a/test/Intlc/EndToEndSpec.hs b/test/Intlc/EndToEndSpec.hs
index 4bc1c57..b443008 100644
--- a/test/Intlc/EndToEndSpec.hs
+++ b/test/Intlc/EndToEndSpec.hs
@@ -72,6 +72,10 @@ spec = describe "end-to-end" $ do
[r|{ "f": { "message": "{x, select, a {hi} b {yo} other {ciao}}", "backend": "ts" } }|]
=*= "export const f: (x: { x: string }) => string = x => `${(() => { switch (x.x) { case 'a': return `hi`; case 'b': return `yo`; default: return `ciao`; } })()}`"
+ it "deeply intersects and unionises arguments" $ do
+ [r|{ "f": { "message": "{name}'s preference: {type, select, email {email} service {{protocol, select, ftp {FTP} http {{isSecure, boolean, true {HTTPS} false {HTTP}}}}}}", "backend": "ts" } }|]
+ =*= "export const f: (x: { name: string } & ({ type: 'email' } | ({ type: 'service' } & ({ protocol: 'ftp' } | ({ protocol: 'http' } & { isSecure: boolean }))))) => string = `${x.name}'s preference: ${(() => { switch (x.type) { case 'email': return `email`; case 'service': return `${(() => { switch (x.protocol) { case 'ftp': return `FTP`; case 'http': return `${(() => { switch (x.isSecure) { case true: return `HTTPS`; case false: return `HTTP`; } })()}`; } })()}`; } })()}`"
+
it "compiles selectordinal" $ do
[r|{ "f": { "message": "{x, selectordinal, one {foo} other {bar}}", "backend": "ts" } }|]
=*= "export const f: (x: { x: number }) => string = x => `${(() => { switch (new Intl.PluralRules('en-US', { type: 'ordinal' }).select(x.x)) { case 'one': return `foo`; default: return `bar`; } })()}`"
Maybe the type signature degrades a bit too much to take this approach? export declare const f: (x: { name: string } & ({ type: 'email' } | ({ type: 'service' } & ({ protocol: 'ftp' } | ({ protocol: 'http' } & { isSecure: boolean }))))) => string We could perhaps merge a little bit more (see at the end) at the cost of some complexity, but... it's not tons better. export declare const f: (x: { name: string } & ({ type: 'email' } | ({ type: 'service' } & ({ protocol: 'ftp' } | ({ protocol: 'http'; isSecure: boolean }))))) => string |
Feel free to rename this issue. I couldn't think of a better name!
Example 1
Extracted from https://crewlabs.slack.com/archives/C0STWEZ2B/p1646839146215689
We have an optional value,
topicTitleOption
of typeOption<string>
. To use it conditionally inside of the ICU message we have to use theselect
/boolean
syntax:However,
hasTopicTitle
is required even whenhasTopic
isfalse
(in which casetopicTitle
won't actually be used inside of the message).topicTitle
should only be required whenhasTopicTitle
istrue
, e.g. perhaps we could generate something like this:Alternatively, we could invent some new syntax to express an optional value:
However I’m not sure how far we can go with that approach given that we need translators to be familiar with the syntax.
Example 2
Note: this example could be split into two separate messages instead of using
select
, but that's not always feasible i.e. if theselect
is surrounded by other text.We have to pass in a dummy value for
serviceName
whenshareType
isemail
.serviceName
should only be required whenshareType
isservice
, e.g. perhaps we could generate something like this:The text was updated successfully, but these errors were encountered: