Skip to content

Commit 806467a

Browse files
authored
preserve language tags (#1354)
1 parent acc4952 commit 806467a

File tree

4 files changed

+41
-8
lines changed

4 files changed

+41
-8
lines changed

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Here are some vague notes on Luxon's design philosophy:
1515

1616
## Building and testing
1717

18-
Building and testing is done through npm scripts. The tests run in Node and require Node 10+ with full-icu support. This is because some of the features available in Luxon (like internationalization and time zones) need that stuff and we test it all. On any platform, if you have Node 10 installed with full-icu, you're good to go; just run npm scripts like `npm run test`. But you probably don't have that, so read on.
18+
Building and testing is done through npm scripts. The tests run in Node and require Node 18 with full-icu support. This is because some of the features available in Luxon (like internationalization and time zones) need that stuff and we test it all. On any platform, if you have Node 18 installed with full-icu, you're good to go; just run `scripts/test`. But you probably don't have that, so read on.
1919

2020
### OSX
2121

src/impl/locale.js

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,27 +70,39 @@ function parseLocaleString(localeStr) {
7070
// b) if it does, use Intl to resolve everything
7171
// c) if Intl fails, try again without the -u
7272

73+
// private subtags and unicode subtags have ordering requirements,
74+
// and we're not properly parsing this, so just strip out the
75+
// private ones if they exist.
76+
const xIndex = localeStr.indexOf("-x-");
77+
if (xIndex !== -1) {
78+
localeStr = localeStr.substring(0, xIndex);
79+
}
80+
7381
const uIndex = localeStr.indexOf("-u-");
7482
if (uIndex === -1) {
7583
return [localeStr];
7684
} else {
7785
let options;
78-
const smaller = localeStr.substring(0, uIndex);
86+
let selectedStr;
7987
try {
8088
options = getCachedDTF(localeStr).resolvedOptions();
89+
selectedStr = localeStr;
8190
} catch (e) {
91+
const smaller = localeStr.substring(0, uIndex);
8292
options = getCachedDTF(smaller).resolvedOptions();
93+
selectedStr = smaller;
8394
}
8495

8596
const { numberingSystem, calendar } = options;
86-
// return the smaller one so that we can append the calendar and numbering overrides to it
87-
return [smaller, numberingSystem, calendar];
97+
return [selectedStr, numberingSystem, calendar];
8898
}
8999
}
90100

91101
function intlConfigString(localeStr, numberingSystem, outputCalendar) {
92102
if (outputCalendar || numberingSystem) {
93-
localeStr += "-u";
103+
if (!localeStr.includes("-u-")) {
104+
localeStr += "-u";
105+
}
94106

95107
if (outputCalendar) {
96108
localeStr += `-ca-${outputCalendar}`;

test/datetime/create.test.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,7 @@ test("DateTime.fromObject accepts a locale", () => {
663663

664664
test("DateTime.fromObject accepts a locale with calendar and numbering identifiers", () => {
665665
const res = DateTime.fromObject({}, { locale: "be-u-ca-coptic-nu-mong" });
666-
expect(res.locale).toBe("be");
666+
expect(res.locale).toBe("be-u-ca-coptic-nu-mong");
667667
expect(res.outputCalendar).toBe("coptic");
668668
expect(res.numberingSystem).toBe("mong");
669669
});
@@ -677,7 +677,7 @@ test("DateTime.fromObject accepts a locale string with weird junk in it", () =>
677677
}
678678
);
679679

680-
expect(res.locale).toBe("be");
680+
expect(res.locale).toBe("be-u-ca-coptic-ca-islamic");
681681

682682
// "coptic" is right, but some versions of Node 10 give "gregory"
683683
expect(res.outputCalendar === "gregory" || res.outputCalendar === "coptic").toBe(true);
@@ -695,7 +695,7 @@ test("DateTime.fromObject overrides the locale string with explicit settings", (
695695
}
696696
);
697697

698-
expect(res.locale).toBe("be");
698+
expect(res.locale).toBe("be-u-ca-coptic-nu-mong");
699699
expect(res.outputCalendar).toBe("islamic");
700700
expect(res.numberingSystem).toBe("thai");
701701
});
@@ -811,3 +811,18 @@ test("DateTime.fromObject takes a undefined to mean {}", () => {
811811
const res = DateTime.fromObject();
812812
expect(res.year).toBe(new Date().getFullYear());
813813
});
814+
815+
test("private language subtags don't break unicode subtags", () => {
816+
const res = DateTime.fromObject(
817+
{},
818+
{
819+
locale: "be-u-ca-coptic-nu-mong-x-twain",
820+
numberingSystem: "thai",
821+
outputCalendar: "islamic",
822+
}
823+
);
824+
825+
expect(res.locale).toBe("be-u-ca-coptic-nu-mong");
826+
expect(res.outputCalendar).toBe("islamic");
827+
expect(res.numberingSystem).toBe("thai");
828+
});

test/datetime/format.test.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,12 @@ test("DateTime#toLocaleString uses locale-appropriate time formats", () => {
415415
expect(dt.reconfigure({ locale: "es" }).toLocaleString(DateTime.TIME_24_SIMPLE)).toBe("9:23");
416416
});
417417

418+
test("DateTime#toLocaleString() respects language tags", () => {
419+
expect(dt.reconfigure({ locale: "en-US-u-hc-h23" }).toLocaleString(DateTime.TIME_SIMPLE)).toBe(
420+
"09:23"
421+
);
422+
});
423+
418424
test("DateTime#toLocaleString() accepts a zone even when the zone is set", () => {
419425
expect(
420426
dt.toLocaleString({

0 commit comments

Comments
 (0)