unsplash / intlc

Compile ICU messages into code. Supports TypeScript and JSX. No runtime.
MIT License
56 stars 2 forks source link

Add ICU prettifier #173

Closed samhh closed 1 year ago

samhh commented 1 year ago

Closes #129. For now the text content must be supplied as per the example instead of via stdin; a change here could be covered by #110.

$ cat x.json
{
  "x": {
    "message": "{hasTags, boolean, true {{type, select, overLimit {{upperLimit, number}+ best free {formattedListOfTags} photos on Unsplash} belowLimit {{photoTotal, number} best free {formattedListOfTags} photos on Unsplash}}} false {{type, select, overLimit {{upperLimit, number}+ best free photos on Unsplash} belowLimit {{photoTotal, number} best free photos on Unsplash}}}} {another, select, a {{foo}} b {bar}}"
  }
}
$ intlc prettify $(cat x.json | jq -r .x.message)
{hasTags, boolean, 
    true {{type, select, 
        overLimit {{upperLimit, number}+ best free {formattedListOfTags} photos on Unsplash}
        belowLimit {{photoTotal, number} best free {formattedListOfTags} photos on Unsplash}
    }}
    false {{type, select, 
        overLimit {{upperLimit, number}+ best free photos on Unsplash}
        belowLimit {{photoTotal, number} best free photos on Unsplash}
    }}
} {another, select, 
    a {{foo}}
    b {bar}
}

There isn't really a satisfying way to format ICU messages across newlines. In this example the space between the hasTags and another interpolations needs to be preserved exactly as-is. Equally formatting in callbacks would be ambiguous, whereas the newlines and indentation inserted here aren't because it's within the syntactic structure of the interpolations.

I think this is okay because as per the feature request, and the part of the example I borrowed from there, we'll mostly be using this for interpolation-heavy, flattened messages.

In terms of implementation, the bulk of the change is refactoring the ICU compiler to be a little more abstract. Following that the change to support formatting is straightforward and centralised, essentially just using Reader local to increment a count according to how deeply nested into "cases" in the AST we are and inserting formatting accordingly.