lingui / lingui/js-lingui

Custom formatters for numbers, dates etc.

Open
#2,279 14 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
5.9k
Forks
457
Avg merge
1d 23h
Merged PRs (30d)
16

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):

```javascript
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:

```javascript
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.
```javascript
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 https://github.com/lingui/js-lingui/issues/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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the plural macro, i18n._, i18n.number, and setupI18n entry points described in the issue, then review how Intl-based formatting currently works. Define a consistent custom-formatting API for message values and instance configuration, including the proposed plural and number/date cases, and document the intended behavior before implementing it.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, typescript
Domain
api, internationalization
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.