-
Notifications
You must be signed in to change notification settings - Fork 159
feat(core): Support locale variants in messages object #360
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
Conversation
packages/core/src/compiler.ts
Outdated
| for (const key of Object.keys(src)) { | ||
| const pl = (plurals && plurals[key]) || plural; | ||
| const normalizedPluralsKey = key.length > 2 ? normalize(key) : key; | ||
| const pl = (plurals && plurals[normalizedPluralsKey]) || plural; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I considered initially making this a double fallback:
const pl = (plurals && plurals[normalizedPluralsKey]) || (plurals && plurals[key]) || plural;
But could not determine whether this covers a desirable fallback path. Could use guidance here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if 1) normalization is to be trusted, and 2) only normalized values are to be supported, then this appears to be a safe refactor
|
It looks like there are some tests failing on master under some versions of node, see: 2bf89a7 for proposed fix |
| const result: StringStructure = {}; | ||
| for (const key of Object.keys(src)) { | ||
| const pl = (plurals && plurals[key]) || plural; | ||
| const normalizedPluralsKey = key.length > 2 ? normalize(key) : key; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we just normalize 💯 % of the time? seems like this length check is already implemented there. may be nice to dedupe it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
normalize will throw if given unexpected input, so no (given that there will be single length keys at some point, we need to ensure that it's a candidate for normalization). Unless we want to catch here, which seems less desirable. Or, we could duplicate the normalize function to be more permissive.
This to me seems like the simplest solution: if the key can be normalized, normalize it. Otherwise use it as-is. Suppose could move to a separate fn, maybeGetNormalizedValue, but it seems like overkill.
| 'Dhuʻl-Hijjah 2, 1426', | ||
| 'Dhuʻl-Hijjah 2, 1426 AH' | ||
| 'Dhuʻl-Hijjah 2, 1426 AH', | ||
| '2 Dhuʻl-Hijjah 1426 AH' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, this looks like the right fix for this test. Would you be ok if I cherry-picked this commit separately from the rest of the PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please do :)
eemeli
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like it may be a breaking change. Consider this case, and how it works at the moment:
// input
const mf = new MessageFormat(['en', 'no']) // English & Norwegian
compileModule(mf, { 'no-one': '{var, plural, one{one} other{other}}' })// output
import { en } from "@messageformat/runtime/lib/cardinals";
import { plural } from "@messageformat/runtime";
export default {
"no-one": (d) => plural(d["var"], 0, en, { one: "one", other: "other" })
}With normalized as well as exact keys getting tested, that message would end up using Norwegian rather than English pluralisation rules. That's a breaking change.
The current documented behaviour is that:
If the
messageformatinstance has been initialized with support for more than one locale, using a key that matches the locale's identifier at any depth of amessagesobject will set its child elements to use that locale.
which in your case ends up interacting with the '*' locale identifier:
If
localehas the special value'*', it will match all available locales. This may be useful if you want your messages to be completely determined by your data, but may provide surprising results if your input message object includes any 2-3 character keys that are not locale identifiers.
The documentation bug here is that the latter part refers to "locale identifiers" and only implicitly specifies that to really mean "BCP-47 primary language subtag".
While I agree that we ought to find a solution for your use case, I think this change shouldn't be it.
|
@eemeli Yes, I was concerned that there may be some edge cases like this. Makes total sense. Ideas for how we might be able to find a solution that works without a breaking change:
That way, by ensuring that the country code / variant is in the set of valid codes if would be very difficult to accidentally specify a key that would be misinterpreted by a variant. Supporting a configuration flag would prevent any accidents at all from happening. However, this would require an additional set of all valid country codes / variants... |
|
Hey @eemeli hope you're well. Do you have any thoughts wrt #360 (comment) Apologies for the bump. We have some work that is currently blocked by this and I'm more than happy to contribute to the codebase if it makes sense. If not, totally understandable-- I can find a workaround in the interim. Thanks so much! |
|
Closing this in favour of #386. |
Ref: #359
It was discovered that when compiling against locale variants (e.g.
en-US,es-MXetc etc...) output is generated against expectations.For example
Where result is
The expectation is instead
Variants are an expected part of locale strings, so it makes sense to support them inside of imports. This bug was caught in our codebase because we want to maintain parity with the icu variant spec.
The patch proposed here is (i think) pretty un-controversial: if a given plural key can be normalized, perform the lookup based on the normalized value.