-
Notifications
You must be signed in to change notification settings - Fork 414
Description
Problem Description
I'm migrating my current project with no i18n library to Lingui and I've faced an issue, that I can't use a custom format for my numbers inside a message. I'm already relying on Intl APIs, but I have some custom functions with additional logic (like special handling of NaNs or some tweaks using DateTimeFormat.formatToParts
) and tunned to my use cases.
Now I can't use them as custom formatters.
Proposed Solution
I want to have an opportunity to pass a custom format function into my macros calls (or even config it globally for the i18n instance).
I think, that can look smth like this in the code (modified docs example):
import { plural } from "@lingui/core/macro";
import { memoizedNumberFormat } from '@lingui/formatters'
const message = plural(numBooks, {
one: plural(numArticles, {
one: `1 book and 1 article`,
other: `1 book and ${numArticles} articles`,
}),
other: plural(numArticles, {
one: `${numBooks} books and 1 article`,
other: `${numBooks} books and ${numArticles} articles`,
}),
}, {
format: {
numBooks: num => num.toString(),
numArticles: memoizedNumberFormat,
}
// or like this for simple cases
// format: memoizedNumberFormat,
});
// β β β β β β
// Generated message was wrapped for better readability
import { i18n } from "@lingui/core";
const message = i18n._(
/*i18n*/ {
id: "XnUh4j",
message: `{numBooks, plural,
one {{numArticles, plural,
one {1 book and 1 article}
other {1 book and {numArticles} articles}
}}
other {{numArticles, plural,
one {{numBooks} books and 1 article}
other {{numBooks} books and {numArticles} articles}
}}
}`,
values: { numBooks, numArticles },
format: {
numBooks: num => num.toString(),
numArticles: memoizedNumberFormat,
}
}
);
Also may be add some default configuration options for i18n instance, like:
import { setupI18n } from "@lingui/core";
import { memoizedNumberFormat, memoizedDateFormat } from '@lingui/formatters'
const i18n = setupI18n({
numberFormatter: memoizedNumberFormat,
dateFormatter: memoizedDateFormat,
});
Alternatives Considered
For now, i've ended up providing 2 variables to my message instead of 1. It works, but that adds overhead for both translators and developers.
const formattedValue = formatInt(defaultValue);
const feedback = t`Default value: ${plural(defaultValue, {
one: `${formattedValue} day`,
other: `${formattedValue} days`,
})}`
I've also though of how can I change my existing codebase to match the library formatting, but that way I don't see a way to handle my additional formatting logic and although Intl methods are the best we ever had for the dates and numbers localisation, they're still not always flexible enough to satisfy the design requirements.
Additional Context
I saw this issue #2265 about making intl formatters deprecated and I agree with the idea there, but I think it can't be done without a more general approach to how values formatting is handled inside the library.
Both i18n.number
method and plural
macro should have similar api and configuration opportunities. That way, we maybe can move the current Intl formatters implementations into a separate tree-shakable package for those, who need an easier adoption path.
I'm not sure, if I'm already have a good enough codebase knowledge for such a significant change. But we can discuss possible solutions and I can try making a PR for that with some assistance, if you agree with the idea itself.