Skip to content
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

Localize preprocessor feature + french locales ordinal day with long month format bug fix #3662

Conversation

fturmel
Copy link
Member

@fturmel fturmel commented Jan 10, 2024

The PR introduces an optional preprocessor function that lives on the locale.localize object. After the format function parses and tokenizes, the preprocessor is invoked with the date and a parts array (the tokens and string literals found in the format string). The preprocessor can modify this array as needed.

This allows us to nicely fix the long standing #1391 french locale day ordinal with long months format regression. This is the best solution I could think of that would not break any public interface and be low overhead. Hope this can benefit other locales too!

As discussed in #3659, I brought back the unit tests from date-fns v1. I also added an additional date and format to the locale snapshots to better surface day ordinal issues (particularly related to the french language) - apologies for the added noise.

CleanShot 2024-01-10 at 14 42 57@2x

Bonus 1: somewhat unrelated, but working on format, I realized that the _originalDate argument sent to the formatters was never relevant (both date and options._originalDate were always the same object). I removed this to simplify things a bit.

Bonus 2: Fixed bad import in main branch that was breaking the tests

Copy link

@antoinerousseau antoinerousseau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice!

@fturmel fturmel force-pushed the PR/localize-preprocessor-feat-and-french-ordinal-fix branch from c895012 to ddac6a5 Compare January 10, 2024 20:00
@fturmel
Copy link
Member Author

fturmel commented Jan 10, 2024

For those specifically interested in the french locale fix, here is the isolated code:

const LONG_MONTHS_TOKENS = ["MMM", "MMMM"];
export const localize: Localize = {
preprocessor: (date, parts) => {
// Replaces the `do` tokens with `d` when used with long month tokens and the day of the month is greater than one.
// Use case "do MMMM" => 1er août, 29 août
// see https://github.com/date-fns/date-fns/issues/1391
if (date.getDate() === 1) return parts;
const hasLongMonthToken = parts.some(
(part) => part.isToken && LONG_MONTHS_TOKENS.includes(part.value),
);
if (!hasLongMonthToken) return parts;
return parts.map((part) =>
part.isToken && part.value === "do"
? { isToken: true, value: "d" }
: part,
);
},

@fturmel fturmel linked an issue Jan 10, 2024 that may be closed by this pull request
@Dallas62
Copy link

Just to make sure, https://github.com/date-fns/date-fns/pull/3662/files#diff-eda4dba459a77e98278dfef21c803e0e1b94faef1d5a3a3c2b42657b8a4a6e58R128 there is an Invalid in the result of parse.
Since it's not the first one in this file I don't think it's blocking, but is it expected ?

@fturmel
Copy link
Member Author

fturmel commented Jan 10, 2024

Just to make sure, https://github.com/date-fns/date-fns/pull/3662/files#diff-eda4dba459a77e98278dfef21c803e0e1b94faef1d5a3a3c2b42657b8a4a6e58R128 there is an Invalid in the result of parse. Since it's not the first one in this file I don't think it's blocking, but is it expected ?

Yes, it's been that way for a while now - I wrote about this in #3136 too

@Dallas62
Copy link

Thanks for the fix and for your time !

@fturmel
Copy link
Member Author

fturmel commented Jan 10, 2024

Thanks for the fix and for your time !

Appreciate your review and all the efforts to surface this issue. Hope the approach is sound and we can eventually get this merged!

@fturmel
Copy link
Member Author

fturmel commented Jan 10, 2024

Oh one other thing I forgot to mention, this only takes into account the MMM and MMMM tokens which are the format context. There are also stand-alone context tokens for long months: LLL and LLLL. Should these also be considered? (I assume not, but wanted to make sure)

https://date-fns.org/docs/format
https://www.unicode.org/reports/tr35/tr35-dates.html#dfst-month

@Dallas62
Copy link

I'm not sure to understand the difference between LLLL and MMMM, even after reading the documentation part about it. I guess it's not important since it's not for "format" ... 😄

@kossnocorp
Copy link
Member

Love it, will try to review it carefully and ship with the next version 🙏

Copy link
Member

@kossnocorp kossnocorp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change is brilliant! I don't know if it will be helpful outside French, but I'll keep my eyes open. If not, and we meet some other nuance in a locale, I'll use a similar preprocessor approach.

src/locale/types.ts Outdated Show resolved Hide resolved
@@ -3,8 +3,7 @@
import assert from "assert";
import { pipe } from "fp-ts/function";
import { flow as jsFnsFlow } from "js-fns";
// @ts-expect-error - Lodash, come on, bro
import { flow as lodashFlow } from "loedash";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, how did it work, and how didn't I miss it? 🤣

@kossnocorp kossnocorp merged commit d36d2eb into date-fns:main Jan 15, 2024
6 checks passed
@fturmel fturmel deleted the PR/localize-preprocessor-feat-and-french-ordinal-fix branch January 15, 2024 15:37
@kossnocorp
Copy link
Member

Shipped with v3.3.0: https://github.com/date-fns/date-fns/releases/tag/v3.3.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Shipped
Development

Successfully merging this pull request may close these issues.

Wrong translation for French.
4 participants