Move polyfill time zone data out of bundles (#18142)

This commit is contained in:
Steve Repsher 2023-10-09 08:28:16 -04:00 committed by GitHub
parent 5b7ef941e4
commit bf9e2cd404
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 33 deletions

View File

@ -1,51 +1,54 @@
import { deleteSync } from "del";
import { mkdir, readFile, writeFile } from "fs/promises";
import gulp from "gulp";
import path from "path";
import { join, resolve } from "node:path";
import paths from "../paths.cjs";
const outDir = path.join(paths.build_dir, "locale-data");
const formatjsDir = join(paths.polymer_dir, "node_modules", "@formatjs");
const outDir = join(paths.build_dir, "locale-data");
const INTL_PACKAGES = {
"intl-relativetimeformat": "RelativeTimeFormat",
const INTL_POLYFILLS = {
"intl-datetimeformat": "DateTimeFormat",
"intl-numberformat": "NumberFormat",
"intl-displaynames": "DisplayNames",
"intl-listformat": "ListFormat",
"intl-numberformat": "NumberFormat",
"intl-relativetimeformat": "RelativeTimeFormat",
};
const convertToJSON = async (pkg, lang) => {
const convertToJSON = async (
pkg,
lang,
subDir = "locale-data",
addFunc = "__addLocaleData",
skipMissing = true
) => {
let localeData;
try {
localeData = await readFile(
path.resolve(
paths.polymer_dir,
`node_modules/@formatjs/${pkg}/locale-data/${lang}.js`
),
join(formatjsDir, pkg, subDir, `${lang}.js`),
"utf-8"
);
} catch (e) {
// Ignore if language is missing (i.e. not supported by @formatjs)
if (e.code === "ENOENT") {
if (e.code === "ENOENT" && skipMissing) {
console.warn(`Skipped missing data for language ${lang} from ${pkg}`);
return;
} else {
}
throw e;
}
}
// Convert to JSON
const className = INTL_PACKAGES[pkg];
localeData = localeData
.replace(
new RegExp(
`\\/\\*\\s*@generated\\s*\\*\\/\\s*\\/\\/\\s*prettier-ignore\\s*if\\s*\\(Intl\\.${className}\\s*&&\\s*typeof\\s*Intl\\.${className}\\.__addLocaleData\\s*===\\s*'function'\\)\\s*{\\s*Intl\\.${className}\\.__addLocaleData\\(`,
"im"
),
""
)
.replace(/\)\s*}/im, "");
const obj = INTL_POLYFILLS[pkg];
const dataRegex = new RegExp(
`Intl\\.${obj}\\.${addFunc}\\((?<data>.*)\\)`,
"s"
);
localeData = localeData.match(dataRegex)?.groups?.data;
if (!localeData) {
throw Error(`Failed to extract data for language ${lang} from ${pkg}`);
}
// Parse to validate JSON, then stringify to minify
localeData = JSON.stringify(JSON.parse(localeData));
await writeFile(path.join(outDir, `${pkg}/${lang}.json`), localeData);
await writeFile(join(outDir, `${pkg}/${lang}.json`), localeData);
};
gulp.task("clean-locale-data", async () => deleteSync([outDir]));
@ -53,17 +56,27 @@ gulp.task("clean-locale-data", async () => deleteSync([outDir]));
gulp.task("create-locale-data", async () => {
const translationMeta = JSON.parse(
await readFile(
path.resolve(paths.translations_src, "translationMetadata.json"),
resolve(paths.translations_src, "translationMetadata.json"),
"utf-8"
)
);
const conversions = [];
for (const pkg of Object.keys(INTL_PACKAGES)) {
await mkdir(path.join(outDir, pkg), { recursive: true });
for (const pkg of Object.keys(INTL_POLYFILLS)) {
// eslint-disable-next-line no-await-in-loop
await mkdir(join(outDir, pkg), { recursive: true });
for (const lang of Object.keys(translationMeta)) {
conversions.push(convertToJSON(pkg, lang));
}
}
conversions.push(
convertToJSON(
"intl-datetimeformat",
"add-all-tz",
".",
"__addTZData",
false
)
);
await Promise.all(conversions);
});

View File

@ -5,7 +5,10 @@ import { shouldPolyfill as shouldPolyfillPluralRules } from "@formatjs/intl-plur
import { shouldPolyfill as shouldPolyfillRelativeTime } from "@formatjs/intl-relativetimeformat/should-polyfill";
import { shouldPolyfill as shouldPolyfillListFormat } from "@formatjs/intl-listformat/should-polyfill";
import { getLocalLanguage } from "../util/common-translation";
import { polyfillLocaleData } from "./locale-data-polyfill";
import {
polyfillLocaleData,
polyfillTimeZoneData,
} from "./locale-data-polyfill";
const polyfillIntl = async () => {
const locale = getLocalLanguage();
@ -22,8 +25,8 @@ const polyfillIntl = async () => {
}
if (shouldPolyfillDateTime(locale)) {
polyfills.push(
import("@formatjs/intl-datetimeformat/polyfill-force").then(
() => import("@formatjs/intl-datetimeformat/add-all-tz")
import("@formatjs/intl-datetimeformat/polyfill-force").then(() =>
polyfillTimeZoneData()
)
);
}

View File

@ -13,16 +13,17 @@ const loadedLocales: Set<string> = new Set();
const addData = async (
obj: (typeof INTL_POLYFILLS)[number],
language: string
language: string,
addFunc = "__addLocaleData"
) => {
// Add function will only exist if constructor is polyfilled
if (typeof (Intl[obj] as any)?.__addLocaleData === "function") {
if (typeof (Intl[obj] as any)?.[addFunc] === "function") {
const result = await fetch(
`${__STATIC_PATH__}locale-data/intl-${obj.toLowerCase()}/${language}.json`
);
// Ignore if polyfill data does not exist for language
if (result.ok) {
(Intl[obj] as any).__addLocaleData(await result.json());
(Intl[obj] as any)[addFunc](await result.json());
}
}
};
@ -34,3 +35,6 @@ export const polyfillLocaleData = async (language: string) => {
loadedLocales.add(language);
await Promise.all(INTL_POLYFILLS.map((obj) => addData(obj, language)));
};
export const polyfillTimeZoneData = () =>
addData("DateTimeFormat", "add-all-tz", "__addTZData");