This reverts commit 1eaeb23c75
.
PR Close #42583
This commit is contained in:
parent
877cde8897
commit
ec6dc78f1d
|
@ -50,5 +50,8 @@ baseline.json
|
||||||
# Ignore .history for the xyz.local-history VSCode extension
|
# Ignore .history for the xyz.local-history VSCode extension
|
||||||
.history
|
.history
|
||||||
|
|
||||||
|
# CLDR data
|
||||||
|
tools/gulp-tasks/cldr/cldr-data/
|
||||||
|
|
||||||
# Husky
|
# Husky
|
||||||
.husky/_
|
.husky/_
|
||||||
|
|
15
WORKSPACE
15
WORKSPACE
|
@ -62,18 +62,3 @@ sass_repositories()
|
||||||
load("@io_bazel_skydoc//skylark:skylark.bzl", "skydoc_repositories")
|
load("@io_bazel_skydoc//skylark:skylark.bzl", "skydoc_repositories")
|
||||||
|
|
||||||
skydoc_repositories()
|
skydoc_repositories()
|
||||||
|
|
||||||
load("//packages/common/locales/generate-locales-tool:cldr-data.bzl", "cldr_data_repository")
|
|
||||||
|
|
||||||
cldr_data_repository(
|
|
||||||
name = "cldr_data",
|
|
||||||
# Since we use the Github archives for CLDR 37, we need to specify a path
|
|
||||||
# to the available locales. This wouldn't be needed with CLDR 39 as that
|
|
||||||
# comes with an official JSON archive not containing a version suffix.
|
|
||||||
available_locales_path = "cldr-core-37.0.0/availableLocales.json",
|
|
||||||
urls = {
|
|
||||||
"https://github.com/unicode-cldr/cldr-core/archive/37.0.0.zip": "32b5c49c3874aa342b90412c207b42e7aefb2435295891fb714c34ce58b3c706",
|
|
||||||
"https://github.com/unicode-cldr/cldr-dates-full/archive/37.0.0.zip": "e1c410dd8ad7d75df4a5393efaf5d28f0d56c0fa126c5d66e171a3f21a988a1e",
|
|
||||||
"https://github.com/unicode-cldr/cldr-numbers-full/archive/37.0.0.zip": "a921b90cf7f436e63fbdd55880f96e39a203acd9e174b0ceafa20a02c242a12e",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
|
@ -20,3 +20,6 @@ function loadTask(fileName, taskName) {
|
||||||
|
|
||||||
gulp.task('source-map-test', loadTask('source-map-test'));
|
gulp.task('source-map-test', loadTask('source-map-test'));
|
||||||
gulp.task('changelog:zonejs', loadTask('changelog-zonejs'));
|
gulp.task('changelog:zonejs', loadTask('changelog-zonejs'));
|
||||||
|
gulp.task('cldr:extract', loadTask('cldr', 'extract'));
|
||||||
|
gulp.task('cldr:download', loadTask('cldr', 'download'));
|
||||||
|
gulp.task('cldr:gen-closure-locale', loadTask('cldr', 'closure'));
|
||||||
|
|
|
@ -164,7 +164,6 @@
|
||||||
"@bazel/buildifier": "^4.0.1",
|
"@bazel/buildifier": "^4.0.1",
|
||||||
"@bazel/ibazel": "^0.15.8",
|
"@bazel/ibazel": "^0.15.8",
|
||||||
"@octokit/graphql": "^4.6.1",
|
"@octokit/graphql": "^4.6.1",
|
||||||
"@types/cldrjs": "^0.4.22",
|
|
||||||
"@types/cli-progress": "^3.4.2",
|
"@types/cli-progress": "^3.4.2",
|
||||||
"@types/conventional-commits-parser": "^3.0.1",
|
"@types/conventional-commits-parser": "^3.0.1",
|
||||||
"@types/ejs": "^3.0.6",
|
"@types/ejs": "^3.0.6",
|
||||||
|
@ -174,7 +173,8 @@
|
||||||
"browserstacktunnel-wrapper": "^2.0.4",
|
"browserstacktunnel-wrapper": "^2.0.4",
|
||||||
"check-side-effects": "0.0.23",
|
"check-side-effects": "0.0.23",
|
||||||
"clang-format": "^1.4.0",
|
"clang-format": "^1.4.0",
|
||||||
"cldr": "5.7.0",
|
"cldr": "7.0.0",
|
||||||
|
"cldr-data-downloader": "^0.3.5",
|
||||||
"cldrjs": "0.5.5",
|
"cldrjs": "0.5.5",
|
||||||
"cli-progress": "^3.7.0",
|
"cli-progress": "^3.7.0",
|
||||||
"conventional-changelog": "^3.1.24",
|
"conventional-changelog": "^3.1.24",
|
||||||
|
@ -217,5 +217,6 @@
|
||||||
"@babel/template": "7.8.6",
|
"@babel/template": "7.8.6",
|
||||||
"@babel/traverse": "7.8.6",
|
"@babel/traverse": "7.8.6",
|
||||||
"@babel/types": "7.8.6"
|
"@babel/types": "7.8.6"
|
||||||
}
|
},
|
||||||
|
"cldr-data-coverage": "full"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
load("//tools:defaults.bzl", "ts_library")
|
|
||||||
|
|
||||||
package(default_visibility = ["//visibility:public"])
|
|
||||||
|
|
||||||
ts_library(
|
|
||||||
name = "generate-locales-tool",
|
|
||||||
srcs = glob(["*.ts"]),
|
|
||||||
deps = [
|
|
||||||
"@npm//@bazel/runfiles",
|
|
||||||
"@npm//@types/cldrjs",
|
|
||||||
"@npm//@types/glob",
|
|
||||||
"@npm//@types/node",
|
|
||||||
"@npm//cldr",
|
|
||||||
"@npm//cldrjs",
|
|
||||||
"@npm//glob",
|
|
||||||
],
|
|
||||||
)
|
|
|
@ -1,35 +0,0 @@
|
||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google LLC All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
|
||||||
* found in the LICENSE file at https://angular.io/license
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* To create smaller locale files, we remove duplicated data.
|
|
||||||
* To make this work we store the data in arrays, where `undefined` indicates that the
|
|
||||||
* value is a duplicate of the previous value in the array.
|
|
||||||
* e.g. consider an array like: [x, y, undefined, z, undefined, undefined]
|
|
||||||
* The first `undefined` is equivalent to y, the second and third are equivalent to z
|
|
||||||
* Note that the first value in an array is always defined.
|
|
||||||
*
|
|
||||||
* Also since we need to know which data is assumed similar, it is important that we store those
|
|
||||||
* similar data in arrays to mark the delimitation between values that have different meanings
|
|
||||||
* (e.g. months and days).
|
|
||||||
*
|
|
||||||
* For further size improvements, "undefined" values will be replaced by a constant in the arrays
|
|
||||||
* as the last step of the file generation (in generateLocale and generateLocaleExtra).
|
|
||||||
* e.g.: [x, y, undefined, z, undefined, undefined] will be [x, y, u, z, u, u]
|
|
||||||
*/
|
|
||||||
export function removeDuplicates(data: unknown[]) {
|
|
||||||
const dedup = [data[0]];
|
|
||||||
for (let i = 1; i < data.length; i++) {
|
|
||||||
if (JSON.stringify(data[i]) !== JSON.stringify(data[i - 1])) {
|
|
||||||
dedup.push(data[i]);
|
|
||||||
} else {
|
|
||||||
dedup.push(undefined);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dedup;
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary")
|
|
||||||
load("//tools:defaults.bzl", "ts_library")
|
|
||||||
|
|
||||||
package(default_visibility = ["//visibility:public"])
|
|
||||||
|
|
||||||
BIN_ENTRYPOINTS = [
|
|
||||||
"get-base-currencies-file",
|
|
||||||
"get-base-locale-file",
|
|
||||||
"get-closure-locale-file",
|
|
||||||
"write-locale-files-to-dist",
|
|
||||||
]
|
|
||||||
|
|
||||||
ts_library(
|
|
||||||
name = "bin",
|
|
||||||
srcs = glob(["*.ts"]),
|
|
||||||
deps = [
|
|
||||||
"//packages/common/locales/generate-locales-tool",
|
|
||||||
"@npm//@types/node",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
[nodejs_binary(
|
|
||||||
name = entrypoint,
|
|
||||||
data = [
|
|
||||||
":bin",
|
|
||||||
"@cldr_data//:all_json",
|
|
||||||
],
|
|
||||||
entry_point = ":%s.ts" % entrypoint,
|
|
||||||
# We need to patch the NodeJS module resolution as this binary runs as
|
|
||||||
# part of a genrule where the linker does not work as expected.
|
|
||||||
# See: https://github.com/bazelbuild/rules_nodejs/issues/2600.
|
|
||||||
templated_args = ["--bazel_patch_module_resolver"],
|
|
||||||
) for entrypoint in BIN_ENTRYPOINTS]
|
|
|
@ -1,17 +0,0 @@
|
||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google LLC All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
|
||||||
* found in the LICENSE file at https://angular.io/license
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base locale used as foundation for other locales. For example: A base locale allows
|
|
||||||
* generation of a file containing all currencies with their corresponding symbols. If we
|
|
||||||
* generate other locales, they can override currency symbols which are different in the base
|
|
||||||
* locale. This means that we do not need re-generate all currencies w/ symbols multiple times,
|
|
||||||
* and allows us to reduce the locale data payload as the base locale is always included.
|
|
||||||
* */
|
|
||||||
export const BASE_LOCALE = 'en';
|
|
|
@ -1,23 +0,0 @@
|
||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google LLC All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
|
||||||
* found in the LICENSE file at https://angular.io/license
|
|
||||||
*/
|
|
||||||
import {CldrData} from '../cldr-data';
|
|
||||||
import {generateBaseCurrenciesFile} from '../locale-base-currencies';
|
|
||||||
|
|
||||||
import {BASE_LOCALE} from './base-locale';
|
|
||||||
|
|
||||||
/** Generates the base currencies file and prints it to the stdout. */
|
|
||||||
function main() {
|
|
||||||
const cldrData = new CldrData();
|
|
||||||
const baseLocaleData = cldrData.getLocaleData(BASE_LOCALE)!;
|
|
||||||
|
|
||||||
process.stdout.write(generateBaseCurrenciesFile(baseLocaleData));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (require.main === module) {
|
|
||||||
main();
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google LLC All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
|
||||||
* found in the LICENSE file at https://angular.io/license
|
|
||||||
*/
|
|
||||||
import {CldrData} from '../cldr-data';
|
|
||||||
import {generateBaseCurrencies} from '../locale-base-currencies';
|
|
||||||
import {generateLocale} from '../locale-file';
|
|
||||||
|
|
||||||
import {BASE_LOCALE} from './base-locale';
|
|
||||||
|
|
||||||
/** Generates the base locale file and prints it to the stdout. */
|
|
||||||
function main() {
|
|
||||||
const cldrData = new CldrData();
|
|
||||||
const baseLocaleData = cldrData.getLocaleData(BASE_LOCALE)!;
|
|
||||||
const baseCurrencies = generateBaseCurrencies(baseLocaleData);
|
|
||||||
|
|
||||||
process.stdout.write(generateLocale(BASE_LOCALE, baseLocaleData, baseCurrencies));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (require.main === module) {
|
|
||||||
main();
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google LLC All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
|
||||||
* found in the LICENSE file at https://angular.io/license
|
|
||||||
*/
|
|
||||||
import {CldrData} from '../cldr-data';
|
|
||||||
import {generateClosureLocaleFile} from '../closure-locale-file';
|
|
||||||
import {generateBaseCurrencies} from '../locale-base-currencies';
|
|
||||||
|
|
||||||
import {BASE_LOCALE} from './base-locale';
|
|
||||||
|
|
||||||
/** Generates the Google3 closure-locale file and prints it to the stdout. */
|
|
||||||
function main() {
|
|
||||||
const cldrData = new CldrData();
|
|
||||||
const baseLocaleData = cldrData.getLocaleData(BASE_LOCALE)!;
|
|
||||||
const baseCurrencies = generateBaseCurrencies(baseLocaleData);
|
|
||||||
|
|
||||||
process.stdout.write(generateClosureLocaleFile(cldrData, baseCurrencies));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (require.main === module) {
|
|
||||||
main();
|
|
||||||
}
|
|
|
@ -1,71 +0,0 @@
|
||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google LLC All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
|
||||||
* found in the LICENSE file at https://angular.io/license
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {writeFileSync} from 'fs';
|
|
||||||
import {join} from 'path';
|
|
||||||
|
|
||||||
import {CldrData} from '../cldr-data';
|
|
||||||
import {generateBaseCurrencies} from '../locale-base-currencies';
|
|
||||||
import {generateLocaleExtra} from '../locale-extra-file';
|
|
||||||
import {generateLocale} from '../locale-file';
|
|
||||||
import {generateLocaleGlobalFile} from '../locale-global-file';
|
|
||||||
|
|
||||||
import {BASE_LOCALE} from './base-locale';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates locale files for each available CLDR locale and writes it to the
|
|
||||||
* specified directory.
|
|
||||||
*/
|
|
||||||
function main(outputDir: string) {
|
|
||||||
const cldrData = new CldrData();
|
|
||||||
const baseLocaleData = cldrData.getLocaleData(BASE_LOCALE)!;
|
|
||||||
const baseCurrencies = generateBaseCurrencies(baseLocaleData);
|
|
||||||
const extraLocaleDir = join(outputDir, 'extra');
|
|
||||||
const globalLocaleDir = join(outputDir, 'global');
|
|
||||||
|
|
||||||
console.info(`Writing locales to: ${outputDir}`);
|
|
||||||
|
|
||||||
// Generate locale files for all locales we have data for.
|
|
||||||
cldrData.availableLocales.forEach((locale: string) => {
|
|
||||||
const localeData = cldrData.getLocaleData(locale);
|
|
||||||
|
|
||||||
// If `cldrjs` is unable to resolve a `bundle` for the current locale, then there is no data
|
|
||||||
// for this locale, and it should not be generated. This can happen as with older versions of
|
|
||||||
// CLDR where `availableLocales.json` specifies locales for which no data is available
|
|
||||||
// (even within the `full` tier packages). See:
|
|
||||||
// http://cldr.unicode.org/development/development-process/design-proposals/json-packaging.
|
|
||||||
// TODO(devversion): Remove if we update to CLDR v39 where this seems fixed. Note that this
|
|
||||||
// worked before in the Gulp tooling without such a check because the `cldr-data-downloader`
|
|
||||||
// overwrote the `availableLocales` to only capture locales with data.
|
|
||||||
if (localeData && !(localeData.attributes as any).bundle) {
|
|
||||||
console.info(`Skipping generation of ${locale} as there is no data.`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const localeFile = generateLocale(locale, localeData, baseCurrencies);
|
|
||||||
const localeExtraFile = generateLocaleExtra(locale, localeData);
|
|
||||||
const localeGlobalFile = generateLocaleGlobalFile(locale, localeData, baseCurrencies);
|
|
||||||
|
|
||||||
writeFileSync(join(outputDir, `${locale}.ts`), localeFile);
|
|
||||||
writeFileSync(join(extraLocaleDir, `${locale}.ts`), localeExtraFile);
|
|
||||||
writeFileSync(join(globalLocaleDir, `${locale}.js`), localeGlobalFile);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (require.main === module) {
|
|
||||||
// The first argument is expected to be a path resolving to a directory
|
|
||||||
// where all locales should be generated into.
|
|
||||||
const outputDir = process.argv[2];
|
|
||||||
|
|
||||||
if (outputDir === undefined) {
|
|
||||||
throw Error('No output directory specified.');
|
|
||||||
}
|
|
||||||
|
|
||||||
main(outputDir);
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
def _cldr_data_repository_impl(ctx):
|
|
||||||
for url, sha256 in ctx.attr.urls.items():
|
|
||||||
ctx.report_progress("Downloading CLDR data from: %s" % url)
|
|
||||||
ctx.download_and_extract(
|
|
||||||
url = url,
|
|
||||||
sha256 = sha256,
|
|
||||||
)
|
|
||||||
|
|
||||||
ctx.report_progress("Extracting available locales from: %s" % ctx.attr.available_locales_path)
|
|
||||||
locales_json = ctx.read(ctx.attr.available_locales_path)
|
|
||||||
locales = json.decode(locales_json)["availableLocales"]["full"]
|
|
||||||
ctx.report_progress("Extracted %s locales from CLDR" % len(locales))
|
|
||||||
|
|
||||||
ctx.file("index.bzl", content = """
|
|
||||||
LOCALES=%s
|
|
||||||
""" % locales)
|
|
||||||
|
|
||||||
ctx.file("BUILD.bazel", content = """
|
|
||||||
filegroup(
|
|
||||||
name = "all_json",
|
|
||||||
srcs = glob(["**/*.json"]),
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
||||||
""")
|
|
||||||
|
|
||||||
"""
|
|
||||||
Repository rule that downloads CLDR data from the specified repository and generates a
|
|
||||||
`BUILD.bazel` file that exposes all data files. Additionally, an `index.bzl` file is generated
|
|
||||||
that exposes a constant for all locales the repository contains data for. This can be used to
|
|
||||||
generate pre-declared outputs.
|
|
||||||
"""
|
|
||||||
cldr_data_repository = repository_rule(
|
|
||||||
implementation = _cldr_data_repository_impl,
|
|
||||||
attrs = {
|
|
||||||
"urls": attr.string_dict(doc = """
|
|
||||||
Dictionary of URLs that resolve to archives containing CLDR JSON data. These archives
|
|
||||||
will be downloaded and extracted at root of the repository. Each key can specify
|
|
||||||
a SHA256 checksum for hermetic builds.
|
|
||||||
""", mandatory = True),
|
|
||||||
"available_locales_path": attr.string(
|
|
||||||
doc = """
|
|
||||||
Relative path to the JSON data file describing all available locales.
|
|
||||||
This file usually resides within the `cldr-core` package
|
|
||||||
""",
|
|
||||||
default = "cldr-core/availableLocales.json",
|
|
||||||
),
|
|
||||||
},
|
|
||||||
)
|
|
|
@ -1,140 +0,0 @@
|
||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google LLC All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
|
||||||
* found in the LICENSE file at https://angular.io/license
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {runfiles} from '@bazel/runfiles';
|
|
||||||
import {CldrStatic} from 'cldrjs';
|
|
||||||
import {sync as globSync} from 'glob';
|
|
||||||
|
|
||||||
// TypeScript doesn't allow us to import the default export without the `esModuleInterop`. We use
|
|
||||||
// the NodeJS require function instead as specifying a custom tsconfig complicates the setup
|
|
||||||
// unnecessarily.
|
|
||||||
// TODO: See if we can improve this by having better types for `cldrjs`.
|
|
||||||
const cldrjs: typeof import('cldrjs') = require('cldrjs');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Globs that match CLDR JSON data files that should be fetched. We limit these intentionally
|
|
||||||
* as loading unused data results in significant slow-down of the generation
|
|
||||||
* (noticeable in local development if locale data is re-generated).
|
|
||||||
*/
|
|
||||||
const CLDR_DATA_GLOBS = [
|
|
||||||
'cldr-core-37.0.0/scriptMetadata.json',
|
|
||||||
'cldr-core-37.0.0/supplemental/**/*.json',
|
|
||||||
'cldr-dates-full-37.0.0/main/**/*.json',
|
|
||||||
'cldr-numbers-full-37.0.0/main/**/*.json',
|
|
||||||
];
|
|
||||||
|
|
||||||
/** Path to the CLDR available locales file. */
|
|
||||||
const CLDR_AVAILABLE_LOCALES_PATH = 'cldr-core-37.0.0/availableLocales.json';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instance providing access to a locale's CLDR data. This type extends the `cldrjs`
|
|
||||||
* instance type with the missing `bundle` attribute property.
|
|
||||||
*/
|
|
||||||
export type CldrLocaleData = CldrStatic&{
|
|
||||||
attributes: {
|
|
||||||
/**
|
|
||||||
* Resolved bundle name for the locale.
|
|
||||||
* More details: http://www.unicode.org/reports/tr35/#Bundle_vs_Item_Lookup
|
|
||||||
*/
|
|
||||||
bundle: string;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class that provides access to the CLDR data downloaded as part of
|
|
||||||
* the `@cldr_data` Bazel repository.
|
|
||||||
*/
|
|
||||||
export class CldrData {
|
|
||||||
/** Path to the CLDR data Bazel repository. i.e. `@cldr_data//`. */
|
|
||||||
readonly cldrDataDir = runfiles.resolve('cldr_data');
|
|
||||||
|
|
||||||
/** List of all available locales CLDR provides data for. */
|
|
||||||
readonly availableLocales: readonly CldrLocaleData[];
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this._loadAndPopulateCldrData();
|
|
||||||
this.availableLocales = this._getAvailableLocales();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets the CLDR data for the specified locale. */
|
|
||||||
getLocaleData(localeName: string): CldrLocaleData|null {
|
|
||||||
// Cast to `CldrLocaleData` because the default `cldrjs` types from `DefinitelyTyped`
|
|
||||||
// are outdated and do not capture the `bundle` attribute. See:
|
|
||||||
// https://github.com/rxaviers/cldrjs#instantiate-a-locale-and-get-it-normalized.
|
|
||||||
const localeData = new cldrjs(localeName) as CldrLocaleData;
|
|
||||||
|
|
||||||
// In case a locale has been requested for which no data is available, we return
|
|
||||||
// `null` immediately instead of returning an empty `CldrStatic` instance.
|
|
||||||
if (localeData.attributes.bundle === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return localeData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets a list of all locales CLDR provides data for. */
|
|
||||||
private _getAvailableLocales(): CldrLocaleData[] {
|
|
||||||
const allLocales =
|
|
||||||
require(`${this.cldrDataDir}/${CLDR_AVAILABLE_LOCALES_PATH}`).availableLocales.full;
|
|
||||||
const localesWithData: CldrLocaleData[] = [];
|
|
||||||
|
|
||||||
for (const localeName of allLocales) {
|
|
||||||
const localeData = this.getLocaleData(localeName);
|
|
||||||
|
|
||||||
// If `cldrjs` is unable to resolve a `bundle` for the current locale, then there is no data
|
|
||||||
// for this locale, and it should not be generated. This can happen as with older versions of
|
|
||||||
// CLDR where `availableLocales.json` specifies locales for which no data is available
|
|
||||||
// (even within the `full` tier packages). See:
|
|
||||||
// http://cldr.unicode.org/development/development-process/design-proposals/json-packaging.
|
|
||||||
// TODO(devversion): Remove if we update to CLDR v39 where this seems fixed. Note that this
|
|
||||||
// worked before in the Gulp tooling without such a check because the `cldr-data-downloader`
|
|
||||||
// overwrote the `availableLocales` to only capture locales with data.
|
|
||||||
if (localeData !== null) {
|
|
||||||
localesWithData.push(localeData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return localesWithData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Loads the CLDR data and populates the `cldrjs` library with it. */
|
|
||||||
private _loadAndPopulateCldrData() {
|
|
||||||
const localeData = this._readCldrDataFromRepository();
|
|
||||||
|
|
||||||
if (localeData.length === 0) {
|
|
||||||
throw Error('No CLDR data could be found.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Populate the `cldrjs` library with the locale data. Note that we need this type cast
|
|
||||||
// to satisfy the first `cldrjs.load` parameter which cannot be undefined.
|
|
||||||
cldrjs.load(...localeData as [object, ...object[]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads the CLDR JSON data from the Bazel repository.
|
|
||||||
* @returns a list of read JSON objects representing the CLDR data.
|
|
||||||
*/
|
|
||||||
private _readCldrDataFromRepository(): object[] {
|
|
||||||
const jsonFiles =
|
|
||||||
CLDR_DATA_GLOBS.map(pattern => globSync(pattern, {cwd: this.cldrDataDir, absolute: true}))
|
|
||||||
.reduce((acc, dataFiles) => [...acc, ...dataFiles], []);
|
|
||||||
|
|
||||||
// Read the JSON for all determined CLDR json files.
|
|
||||||
return jsonFiles.map(filePath => {
|
|
||||||
const parsed = require(filePath);
|
|
||||||
|
|
||||||
// Guards against cases where non-CLDR data files are accidentally picked up
|
|
||||||
// by the glob above and would throw-off the bundle lookup in `cldrjs`.
|
|
||||||
if (parsed.main !== undefined && typeof parsed.main !== 'object') {
|
|
||||||
throw Error('Unexpected CLDR json file with "main" field which is not an object.');
|
|
||||||
}
|
|
||||||
|
|
||||||
return parsed;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,153 +0,0 @@
|
||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google LLC All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
|
||||||
* found in the LICENSE file at https://angular.io/license
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {CldrData} from './cldr-data';
|
|
||||||
import {fileHeader} from './file-header';
|
|
||||||
import {BaseCurrencies} from './locale-base-currencies';
|
|
||||||
import {generateLocale} from './locale-file';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of locales used by Closure. These locales will be incorporated in the generated
|
|
||||||
* closure locale file. See:
|
|
||||||
* https://github.com/google/closure-library/blob/master/closure/goog/i18n/datetimepatterns.js#L2450
|
|
||||||
*/
|
|
||||||
const GOOG_LOCALES = [
|
|
||||||
'af', 'am', 'ar', 'ar-DZ', 'az', 'be', 'bg', 'bn', 'br', 'bs',
|
|
||||||
'ca', 'chr', 'cs', 'cy', 'da', 'de', 'de-AT', 'de-CH', 'el', 'en-AU',
|
|
||||||
'en-CA', 'en-GB', 'en-IE', 'en-IN', 'en-SG', 'en-ZA', 'es', 'es-419', 'es-MX', 'es-US',
|
|
||||||
'et', 'eu', 'fa', 'fi', 'fr', 'fr-CA', 'ga', 'gl', 'gsw', 'gu',
|
|
||||||
'haw', 'hi', 'hr', 'hu', 'hy', 'in', 'is', 'it', 'iw', 'ja',
|
|
||||||
'ka', 'kk', 'km', 'kn', 'ko', 'ky', 'ln', 'lo', 'lt', 'lv',
|
|
||||||
'mk', 'ml', 'mn', 'mo', 'mr', 'ms', 'mt', 'my', 'ne', 'nl',
|
|
||||||
'no', 'or', 'pa', 'pl', 'pt', 'pt-PT', 'ro', 'ru', 'sh', 'si',
|
|
||||||
'sk', 'sl', 'sq', 'sr', 'sv', 'sw', 'ta', 'te', 'th', 'tl',
|
|
||||||
'tr', 'uk', 'ur', 'uz', 'vi', 'zh', 'zh-CN', 'zh-HK', 'zh-TW', 'zu'
|
|
||||||
];
|
|
||||||
|
|
||||||
export function generateClosureLocaleFile(
|
|
||||||
cldrData: CldrData, baseCurrencies: BaseCurrencies): string {
|
|
||||||
// locale id aliases to support deprecated locale ids used by closure
|
|
||||||
// it maps deprecated ids --> new ids
|
|
||||||
// manually extracted from ./cldr-data/supplemental/aliases.json
|
|
||||||
// TODO: Consider extracting directly from the CLDR data instead.
|
|
||||||
const aliases = {
|
|
||||||
'in': 'id',
|
|
||||||
'iw': 'he',
|
|
||||||
'mo': 'ro-MD',
|
|
||||||
'no': 'nb',
|
|
||||||
'nb': 'no-NO',
|
|
||||||
'sh': 'sr-Latn',
|
|
||||||
'tl': 'fil',
|
|
||||||
'pt': 'pt-BR',
|
|
||||||
'zh-CN': 'zh-Hans-CN',
|
|
||||||
'zh-Hans-CN': 'zh-Hans',
|
|
||||||
'zh-HK': 'zh-Hant-HK',
|
|
||||||
'zh-TW': 'zh-Hant-TW',
|
|
||||||
'zh-Hant-TW': 'zh-Hant',
|
|
||||||
};
|
|
||||||
|
|
||||||
return generateAllLocalesFile(cldrData, GOOG_LOCALES, aliases, baseCurrencies);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a file that contains all locale to import for closure.
|
|
||||||
* Tree shaking will only keep the data for the `goog.LOCALE` locale.
|
|
||||||
*/
|
|
||||||
function generateAllLocalesFile(
|
|
||||||
cldrData: CldrData, locales: string[], aliases: {[name: string]: string},
|
|
||||||
baseCurrencies: BaseCurrencies) {
|
|
||||||
const existingLocalesAliases: {[locale: string]: Set<string>} = {};
|
|
||||||
const existingLocalesData: {[locale: string]: string} = {};
|
|
||||||
|
|
||||||
// for each locale, get the data and the list of equivalent locales
|
|
||||||
locales.forEach(locale => {
|
|
||||||
const eqLocales = new Set<string>();
|
|
||||||
eqLocales.add(locale);
|
|
||||||
if (locale.match(/-/)) {
|
|
||||||
eqLocales.add(locale.replace(/-/g, '_'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for aliases
|
|
||||||
const alias = aliases[locale];
|
|
||||||
if (alias) {
|
|
||||||
eqLocales.add(alias);
|
|
||||||
|
|
||||||
if (alias.match(/-/)) {
|
|
||||||
eqLocales.add(alias.replace(/-/g, '_'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// to avoid duplicated "case" we regroup all locales in the same "case"
|
|
||||||
// the simplest way to do that is to have alias aliases
|
|
||||||
// e.g. 'no' --> 'nb', 'nb' --> 'no-NO'
|
|
||||||
// which means that we'll have 'no', 'nb' and 'no-NO' in the same "case"
|
|
||||||
const aliasKeys = Object.keys(aliases);
|
|
||||||
for (let i = 0; i < aliasKeys.length; i++) {
|
|
||||||
const aliasValue = aliases[alias];
|
|
||||||
if (aliasKeys.indexOf(alias) !== -1 && !eqLocales.has(aliasValue)) {
|
|
||||||
eqLocales.add(aliasValue);
|
|
||||||
|
|
||||||
if (aliasValue.match(/-/)) {
|
|
||||||
eqLocales.add(aliasValue.replace(/-/g, '_'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const localeNameForData = aliases[locale] ?? locale;
|
|
||||||
const localeData = cldrData.getLocaleData(localeNameForData);
|
|
||||||
const localeName = formatLocale(locale);
|
|
||||||
existingLocalesData[locale] =
|
|
||||||
generateLocale(localeNameForData, localeData, baseCurrencies)
|
|
||||||
.replace(`${fileHeader}\n`, '')
|
|
||||||
.replace('export default ', `export const locale_${localeName} = `)
|
|
||||||
.replace('function plural', `function plural_${localeName}`)
|
|
||||||
.replace(/,\s+plural/, `, plural_${localeName}`)
|
|
||||||
.replace(/\s*const u = undefined;\s*/, '');
|
|
||||||
|
|
||||||
existingLocalesAliases[locale] = eqLocales;
|
|
||||||
});
|
|
||||||
|
|
||||||
function generateCases(locale: string) {
|
|
||||||
let str = '';
|
|
||||||
let locales: string[] = [];
|
|
||||||
const eqLocales = existingLocalesAliases[locale];
|
|
||||||
eqLocales.forEach(l => {
|
|
||||||
str += `case '${l}':\n`;
|
|
||||||
locales.push(`'${l}'`);
|
|
||||||
});
|
|
||||||
let localesStr = '[' + locales.join(',') + ']';
|
|
||||||
|
|
||||||
str += ` l = locale_${formatLocale(locale)};
|
|
||||||
locales = ${localesStr};
|
|
||||||
break;\n`;
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
return `${fileHeader}
|
|
||||||
|
|
||||||
import {registerLocaleData} from '../src/i18n/locale_data';
|
|
||||||
|
|
||||||
const u = undefined;
|
|
||||||
|
|
||||||
${locales.map(locale => `${existingLocalesData[locale]}`).join('\n')}
|
|
||||||
|
|
||||||
let l: any;
|
|
||||||
let locales: string[] = [];
|
|
||||||
|
|
||||||
switch (goog.LOCALE) {
|
|
||||||
${locales.map(locale => generateCases(locale)).join('')}}
|
|
||||||
|
|
||||||
if(l) {
|
|
||||||
locales.forEach(locale => registerLocaleData(l, locale));
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatLocale(locale: string): string {
|
|
||||||
return locale.replace(/-/g, '_');
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google LLC All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
|
||||||
* found in the LICENSE file at https://angular.io/license
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {CldrLocaleData} from './cldr-data';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns data for the chosen day periods
|
|
||||||
*/
|
|
||||||
export function getDayPeriods(localeData: CldrLocaleData, dayPeriodsList: string[]): {
|
|
||||||
format: {narrow: string[], abbreviated: string[], wide: string[]},
|
|
||||||
'stand-alone': {narrow: string[], abbreviated: string[], wide: string[]}
|
|
||||||
} {
|
|
||||||
const dayPeriods = localeData.main(`dates/calendars/gregorian/dayPeriods`);
|
|
||||||
const result: any = {};
|
|
||||||
// cleaning up unused keys
|
|
||||||
Object.keys(dayPeriods).forEach(key1 => { // format / stand-alone
|
|
||||||
result[key1] = {};
|
|
||||||
Object.keys(dayPeriods[key1]).forEach(key2 => { // narrow / abbreviated / wide
|
|
||||||
result[key1][key2] = {};
|
|
||||||
Object.keys(dayPeriods[key1][key2]).forEach(key3 => {
|
|
||||||
if (dayPeriodsList.indexOf(key3) !== -1) {
|
|
||||||
result[key1][key2][key3] = dayPeriods[key1][key2][key3];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return result as any;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns day period rules for a locale
|
|
||||||
* @returns string[]
|
|
||||||
*/
|
|
||||||
export function getDayPeriodRules(localeData: CldrLocaleData): {[key: string]: []} {
|
|
||||||
const dayPeriodRules =
|
|
||||||
localeData.get(`supplemental/dayPeriodRuleSet/${localeData.attributes.language}`);
|
|
||||||
const rules: any = {};
|
|
||||||
|
|
||||||
if (dayPeriodRules) {
|
|
||||||
Object.keys(dayPeriodRules).forEach(key => {
|
|
||||||
if (dayPeriodRules[key]._at) {
|
|
||||||
rules[key] = dayPeriodRules[key]._at;
|
|
||||||
} else {
|
|
||||||
rules[key] = [dayPeriodRules[key]._from, dayPeriodRules[key]._before];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return rules;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the basic day periods (am/pm)
|
|
||||||
*/
|
|
||||||
export function getDayPeriodsAmPm(localeData: CldrLocaleData) {
|
|
||||||
return getDayPeriods(localeData, ['am', 'pm']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the extra day periods (without am/pm)
|
|
||||||
*/
|
|
||||||
export function getDayPeriodsNoAmPm(localeData: CldrLocaleData) {
|
|
||||||
return getDayPeriods(localeData, [
|
|
||||||
'noon', 'midnight', 'morning1', 'morning2', 'afternoon1', 'afternoon2', 'evening1', 'evening2',
|
|
||||||
'night1', 'night2'
|
|
||||||
]);
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google LLC All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
|
||||||
* found in the LICENSE file at https://angular.io/license
|
|
||||||
*/
|
|
||||||
|
|
||||||
export const fileHeader = `/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google LLC All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
|
||||||
* found in the LICENSE file at https://angular.io/license
|
|
||||||
*/
|
|
||||||
|
|
||||||
// THIS CODE IS GENERATED - DO NOT MODIFY.`;
|
|
|
@ -1,74 +0,0 @@
|
||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google LLC All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
|
||||||
* found in the LICENSE file at https://angular.io/license
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {CldrLocaleData} from './cldr-data';
|
|
||||||
import {fileHeader} from './file-header';
|
|
||||||
import {stringify} from './object-stringify';
|
|
||||||
|
|
||||||
export type BaseCurrencySymbols = [
|
|
||||||
string
|
|
||||||
]|[string | undefined, string]|[string, undefined, number]|[string | undefined, string, number];
|
|
||||||
|
|
||||||
export type BaseCurrencies = {
|
|
||||||
[code: string]: BaseCurrencySymbols|undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a file that contains the list of currencies, their symbols and digits.
|
|
||||||
*/
|
|
||||||
export function generateBaseCurrenciesFile(baseLocaleData: CldrLocaleData) {
|
|
||||||
const baseCurrencies = generateBaseCurrencies(baseLocaleData);
|
|
||||||
|
|
||||||
return `${fileHeader}
|
|
||||||
export type CurrenciesSymbols = [string] | [string | undefined, string];
|
|
||||||
|
|
||||||
/** @internal */
|
|
||||||
export const CURRENCIES_EN: {[code: string]: CurrenciesSymbols | [string | undefined, string | undefined, number]} = ${
|
|
||||||
stringify(baseCurrencies)};
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a list of currencies to be used as a base for other currencies
|
|
||||||
* e.g.: {'ARS': [, '$'], 'AUD': ['A$', '$'], ...}
|
|
||||||
*/
|
|
||||||
export function generateBaseCurrencies(localeData: CldrLocaleData) {
|
|
||||||
const currenciesData = localeData.main('numbers/currencies');
|
|
||||||
const fractions = localeData.get(`supplemental/currencyData/fractions`);
|
|
||||||
const currencies: BaseCurrencies = {};
|
|
||||||
|
|
||||||
Object.keys(currenciesData).forEach(key => {
|
|
||||||
let symbolsArray = [];
|
|
||||||
const symbol = currenciesData[key].symbol;
|
|
||||||
const symbolNarrow = currenciesData[key]['symbol-alt-narrow'];
|
|
||||||
if (symbol && symbol !== key) {
|
|
||||||
symbolsArray.push(symbol);
|
|
||||||
}
|
|
||||||
if (symbolNarrow && symbolNarrow !== symbol) {
|
|
||||||
if (symbolsArray.length > 0) {
|
|
||||||
symbolsArray.push(symbolNarrow);
|
|
||||||
} else {
|
|
||||||
symbolsArray = [undefined, symbolNarrow];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fractions[key] && fractions[key]['_digits']) {
|
|
||||||
const digits = parseInt(fractions[key]['_digits'], 10);
|
|
||||||
if (symbolsArray.length === 2) {
|
|
||||||
symbolsArray.push(digits);
|
|
||||||
} else if (symbolsArray.length === 1) {
|
|
||||||
symbolsArray = [...symbolsArray, undefined, digits];
|
|
||||||
} else {
|
|
||||||
symbolsArray = [undefined, undefined, digits];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (symbolsArray.length > 0) {
|
|
||||||
currencies[key] = symbolsArray as BaseCurrencySymbols;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return currencies;
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google LLC All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
|
||||||
* found in the LICENSE file at https://angular.io/license
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {CldrLocaleData} from './cldr-data';
|
|
||||||
import {BaseCurrencies} from './locale-base-currencies';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* To minimize the file even more, we only output the differences compared to the base currency
|
|
||||||
*/
|
|
||||||
export function generateLocaleCurrencies(
|
|
||||||
localeData: CldrLocaleData, baseCurrencies: BaseCurrencies) {
|
|
||||||
const currenciesData = localeData.main('numbers/currencies');
|
|
||||||
const currencies: any = {};
|
|
||||||
|
|
||||||
Object.keys(currenciesData).forEach(code => {
|
|
||||||
let symbolsArray = [];
|
|
||||||
const symbol = currenciesData[code].symbol;
|
|
||||||
const symbolNarrow = currenciesData[code]['symbol-alt-narrow'];
|
|
||||||
if (symbol && symbol !== code) {
|
|
||||||
symbolsArray.push(symbol);
|
|
||||||
}
|
|
||||||
if (symbolNarrow && symbolNarrow !== symbol) {
|
|
||||||
if (symbolsArray.length > 0) {
|
|
||||||
symbolsArray.push(symbolNarrow);
|
|
||||||
} else {
|
|
||||||
symbolsArray = [undefined, symbolNarrow];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseCurrencySymbols = baseCurrencies[code] || [];
|
|
||||||
|
|
||||||
// Jf locale data is equal to the one in the base currencies, skip this currency to
|
|
||||||
// avoid unnecessary locale data that could be inferred from the base currency.
|
|
||||||
if (baseCurrencySymbols && baseCurrencySymbols[0] === symbolsArray[0] &&
|
|
||||||
baseCurrencySymbols[1] === symbolsArray[1]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
currencies[code] = symbolsArray;
|
|
||||||
});
|
|
||||||
return currencies;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the currency code, symbol and name for a locale
|
|
||||||
*/
|
|
||||||
export function getCurrencySettings(localeName: string, localeData: CldrLocaleData) {
|
|
||||||
const currencyInfo = localeData.main(`numbers/currencies`);
|
|
||||||
let currentCurrency = '';
|
|
||||||
|
|
||||||
// find the currency currently used in this country
|
|
||||||
const currencies: any[] =
|
|
||||||
localeData.get(`supplemental/currencyData/region/${localeData.attributes.territory}`) ||
|
|
||||||
localeData.get(
|
|
||||||
`supplemental/currencyData/region/${localeData.attributes.language.toUpperCase()}`);
|
|
||||||
|
|
||||||
if (currencies) {
|
|
||||||
currencies.some(currency => {
|
|
||||||
const keys = Object.keys(currency);
|
|
||||||
return keys.some(key => {
|
|
||||||
if (currency[key]._from && !currency[key]._to) {
|
|
||||||
return currentCurrency = key;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!currentCurrency) {
|
|
||||||
throw new Error(`Unable to find currency for locale "${localeName}"`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let currencySettings = [undefined, undefined, undefined];
|
|
||||||
|
|
||||||
if (currentCurrency) {
|
|
||||||
currencySettings = [
|
|
||||||
currentCurrency, currencyInfo[currentCurrency].symbol,
|
|
||||||
currencyInfo[currentCurrency].displayName
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return currencySettings;
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google LLC All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
|
||||||
* found in the LICENSE file at https://angular.io/license
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {removeDuplicates} from './array-deduplication';
|
|
||||||
import {CldrLocaleData} from './cldr-data';
|
|
||||||
import {getDayPeriodRules, getDayPeriodsNoAmPm} from './day-periods';
|
|
||||||
import {fileHeader} from './file-header';
|
|
||||||
import {stringify} from './object-stringify';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate the contents for the extra data file
|
|
||||||
*/
|
|
||||||
export function generateLocaleExtra(locale: string, localeData: CldrLocaleData) {
|
|
||||||
return `${fileHeader}
|
|
||||||
const u = undefined;
|
|
||||||
|
|
||||||
export default ${generateDayPeriodsSupplementalString(locale, localeData)};
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Collect up the day period rules, and extended day period data.
|
|
||||||
*/
|
|
||||||
export function generateDayPeriodsSupplementalString(locale: string, localeData: CldrLocaleData) {
|
|
||||||
const dayPeriods = getDayPeriodsNoAmPm(localeData);
|
|
||||||
const dayPeriodRules = getDayPeriodRules(localeData);
|
|
||||||
|
|
||||||
let dayPeriodsSupplemental: any[] = [];
|
|
||||||
if (Object.keys(dayPeriods.format.narrow).length) {
|
|
||||||
const keys = Object.keys(dayPeriods.format.narrow);
|
|
||||||
|
|
||||||
if (keys.length !== Object.keys(dayPeriodRules).length) {
|
|
||||||
throw new Error(`Error: locale ${locale} has not the correct number of day period rules`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const dayPeriodsFormat = removeDuplicates([
|
|
||||||
Object.values(dayPeriods.format.narrow), Object.values(dayPeriods.format.abbreviated),
|
|
||||||
Object.values(dayPeriods.format.wide)
|
|
||||||
]);
|
|
||||||
|
|
||||||
const dayPeriodsStandalone = removeDuplicates([
|
|
||||||
Object.values(dayPeriods['stand-alone'].narrow),
|
|
||||||
Object.values(dayPeriods['stand-alone'].abbreviated),
|
|
||||||
Object.values(dayPeriods['stand-alone'].wide)
|
|
||||||
]);
|
|
||||||
|
|
||||||
const rules = keys.map(key => dayPeriodRules[key]);
|
|
||||||
dayPeriodsSupplemental = [...removeDuplicates([dayPeriodsFormat, dayPeriodsStandalone]), rules];
|
|
||||||
}
|
|
||||||
return stringify(dayPeriodsSupplemental).replace(/undefined/g, 'u');
|
|
||||||
}
|
|
|
@ -1,225 +0,0 @@
|
||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google LLC All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
|
||||||
* found in the LICENSE file at https://angular.io/license
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {removeDuplicates} from './array-deduplication';
|
|
||||||
import {CldrLocaleData} from './cldr-data';
|
|
||||||
import {getDayPeriodsAmPm} from './day-periods';
|
|
||||||
import {fileHeader} from './file-header';
|
|
||||||
import {BaseCurrencies} from './locale-base-currencies';
|
|
||||||
import {generateLocaleCurrencies, getCurrencySettings} from './locale-currencies';
|
|
||||||
import {stringify} from './object-stringify';
|
|
||||||
import {getPluralFunction} from './plural-function';
|
|
||||||
|
|
||||||
const WEEK_DAYS = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
|
|
||||||
|
|
||||||
/** Generate contents for the basic locale data file */
|
|
||||||
export function generateLocale(
|
|
||||||
locale: string, localeData: CldrLocaleData, baseCurrencies: BaseCurrencies) {
|
|
||||||
return `${fileHeader}
|
|
||||||
const u = undefined;
|
|
||||||
|
|
||||||
${getPluralFunction(locale)}
|
|
||||||
|
|
||||||
export default ${generateBasicLocaleString(locale, localeData, baseCurrencies)};
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Collect up the basic locale data [ localeId, dateTime, number, currency, directionality,
|
|
||||||
* pluralCase ].
|
|
||||||
*/
|
|
||||||
export function generateBasicLocaleString(
|
|
||||||
locale: string, localeData: CldrLocaleData, baseCurrencies: BaseCurrencies) {
|
|
||||||
let data = stringify([
|
|
||||||
locale,
|
|
||||||
...getDateTimeTranslations(localeData),
|
|
||||||
...getDateTimeSettings(localeData),
|
|
||||||
...getNumberSettings(localeData),
|
|
||||||
...getCurrencySettings(locale, localeData),
|
|
||||||
generateLocaleCurrencies(localeData, baseCurrencies),
|
|
||||||
getDirectionality(localeData),
|
|
||||||
])
|
|
||||||
// We remove "undefined" added by spreading arrays when there is no value
|
|
||||||
.replace(/undefined/g, 'u');
|
|
||||||
|
|
||||||
// adding plural function after, because we don't want it as a string. The function named `plural`
|
|
||||||
// is expected to be available in the file. See `generateLocale` above.
|
|
||||||
data = data.replace(/\]$/, ', plural]');
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the writing direction for a locale
|
|
||||||
* @returns 'rtl' | 'ltr'
|
|
||||||
*/
|
|
||||||
function getDirectionality(localeData: CldrLocaleData): 'rtl'|'ltr' {
|
|
||||||
const rtl = localeData.get('scriptMetadata/{script}/rtl');
|
|
||||||
return rtl === 'YES' ? 'rtl' : 'ltr';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns dateTime data for a locale
|
|
||||||
* @returns [ firstDayOfWeek, weekendRange, formats ]
|
|
||||||
*/
|
|
||||||
function getDateTimeSettings(localeData: CldrLocaleData) {
|
|
||||||
return [
|
|
||||||
getFirstDayOfWeek(localeData), getWeekendRange(localeData), ...getDateTimeFormats(localeData)
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number symbols and formats for a locale
|
|
||||||
* @returns [ symbols, formats ]
|
|
||||||
* symbols: [ decimal, group, list, percentSign, plusSign, minusSign, exponential,
|
|
||||||
* superscriptingExponent, perMille, infinity, nan, timeSeparator, currencyDecimal?, currencyGroup?
|
|
||||||
* ]
|
|
||||||
* formats: [ currency, decimal, percent, scientific ]
|
|
||||||
*/
|
|
||||||
function getNumberSettings(localeData: CldrLocaleData) {
|
|
||||||
const decimalFormat = localeData.main('numbers/decimalFormats-numberSystem-latn/standard');
|
|
||||||
const percentFormat = localeData.main('numbers/percentFormats-numberSystem-latn/standard');
|
|
||||||
const scientificFormat = localeData.main('numbers/scientificFormats-numberSystem-latn/standard');
|
|
||||||
const currencyFormat = localeData.main('numbers/currencyFormats-numberSystem-latn/standard');
|
|
||||||
const symbols = localeData.main('numbers/symbols-numberSystem-latn');
|
|
||||||
const symbolValues = [
|
|
||||||
symbols.decimal,
|
|
||||||
symbols.group,
|
|
||||||
symbols.list,
|
|
||||||
symbols.percentSign,
|
|
||||||
symbols.plusSign,
|
|
||||||
symbols.minusSign,
|
|
||||||
symbols.exponential,
|
|
||||||
symbols.superscriptingExponent,
|
|
||||||
symbols.perMille,
|
|
||||||
symbols.infinity,
|
|
||||||
symbols.nan,
|
|
||||||
symbols.timeSeparator,
|
|
||||||
];
|
|
||||||
|
|
||||||
if (symbols.currencyDecimal || symbols.currencyGroup) {
|
|
||||||
symbolValues.push(symbols.currencyDecimal);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (symbols.currencyGroup) {
|
|
||||||
symbolValues.push(symbols.currencyGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [symbolValues, [decimalFormat, percentFormat, currencyFormat, scientificFormat]];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns week-end range for a locale, based on US week days
|
|
||||||
* @returns [number, number]
|
|
||||||
*/
|
|
||||||
function getWeekendRange(localeData: CldrLocaleData) {
|
|
||||||
const startDay =
|
|
||||||
localeData.get(`supplemental/weekData/weekendStart/${localeData.attributes.territory}`) ||
|
|
||||||
localeData.get('supplemental/weekData/weekendStart/001');
|
|
||||||
const endDay =
|
|
||||||
localeData.get(`supplemental/weekData/weekendEnd/${localeData.attributes.territory}`) ||
|
|
||||||
localeData.get('supplemental/weekData/weekendEnd/001');
|
|
||||||
return [WEEK_DAYS.indexOf(startDay), WEEK_DAYS.indexOf(endDay)];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns date-related translations for a locale
|
|
||||||
* @returns [ dayPeriodsFormat, dayPeriodsStandalone, daysFormat, dayStandalone, monthsFormat,
|
|
||||||
* monthsStandalone, eras ]
|
|
||||||
* each value: [ narrow, abbreviated, wide, short? ]
|
|
||||||
*/
|
|
||||||
function getDateTimeTranslations(localeData: CldrLocaleData) {
|
|
||||||
const dayNames = localeData.main(`dates/calendars/gregorian/days`);
|
|
||||||
const monthNames = localeData.main(`dates/calendars/gregorian/months`);
|
|
||||||
const erasNames = localeData.main(`dates/calendars/gregorian/eras`);
|
|
||||||
const dayPeriods = getDayPeriodsAmPm(localeData);
|
|
||||||
|
|
||||||
const dayPeriodsFormat = removeDuplicates([
|
|
||||||
Object.values(dayPeriods.format.narrow), Object.values(dayPeriods.format.abbreviated),
|
|
||||||
Object.values(dayPeriods.format.wide)
|
|
||||||
]);
|
|
||||||
|
|
||||||
const dayPeriodsStandalone = removeDuplicates([
|
|
||||||
Object.values(dayPeriods['stand-alone'].narrow),
|
|
||||||
Object.values(dayPeriods['stand-alone'].abbreviated),
|
|
||||||
Object.values(dayPeriods['stand-alone'].wide)
|
|
||||||
]);
|
|
||||||
|
|
||||||
const daysFormat = removeDuplicates([
|
|
||||||
Object.values(dayNames.format.narrow), Object.values(dayNames.format.abbreviated),
|
|
||||||
Object.values(dayNames.format.wide), Object.values(dayNames.format.short)
|
|
||||||
]);
|
|
||||||
|
|
||||||
const daysStandalone = removeDuplicates([
|
|
||||||
Object.values(dayNames['stand-alone'].narrow),
|
|
||||||
Object.values(dayNames['stand-alone'].abbreviated), Object.values(dayNames['stand-alone'].wide),
|
|
||||||
Object.values(dayNames['stand-alone'].short)
|
|
||||||
]);
|
|
||||||
|
|
||||||
const monthsFormat = removeDuplicates([
|
|
||||||
Object.values(monthNames.format.narrow), Object.values(monthNames.format.abbreviated),
|
|
||||||
Object.values(monthNames.format.wide)
|
|
||||||
]);
|
|
||||||
|
|
||||||
const monthsStandalone = removeDuplicates([
|
|
||||||
Object.values(monthNames['stand-alone'].narrow),
|
|
||||||
Object.values(monthNames['stand-alone'].abbreviated),
|
|
||||||
Object.values(monthNames['stand-alone'].wide)
|
|
||||||
]);
|
|
||||||
|
|
||||||
const eras = removeDuplicates([
|
|
||||||
[erasNames.eraNarrow['0'], erasNames.eraNarrow['1']],
|
|
||||||
[erasNames.eraAbbr['0'], erasNames.eraAbbr['1']],
|
|
||||||
[erasNames.eraNames['0'], erasNames.eraNames['1']]
|
|
||||||
]);
|
|
||||||
|
|
||||||
const dateTimeTranslations = [
|
|
||||||
...removeDuplicates([dayPeriodsFormat, dayPeriodsStandalone]),
|
|
||||||
...removeDuplicates([daysFormat, daysStandalone]),
|
|
||||||
...removeDuplicates([monthsFormat, monthsStandalone]), eras
|
|
||||||
];
|
|
||||||
|
|
||||||
return dateTimeTranslations;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns date, time and dateTime formats for a locale
|
|
||||||
* @returns [dateFormats, timeFormats, dateTimeFormats]
|
|
||||||
* each format: [ short, medium, long, full ]
|
|
||||||
*/
|
|
||||||
function getDateTimeFormats(localeData: CldrLocaleData) {
|
|
||||||
function getFormats(data: any) {
|
|
||||||
return removeDuplicates([
|
|
||||||
data.short._value || data.short, data.medium._value || data.medium,
|
|
||||||
data.long._value || data.long, data.full._value || data.full
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
const dateFormats = localeData.main('dates/calendars/gregorian/dateFormats');
|
|
||||||
const timeFormats = localeData.main('dates/calendars/gregorian/timeFormats');
|
|
||||||
const dateTimeFormats = localeData.main('dates/calendars/gregorian/dateTimeFormats');
|
|
||||||
|
|
||||||
return [getFormats(dateFormats), getFormats(timeFormats), getFormats(dateTimeFormats)];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the first day of the week, based on US week days
|
|
||||||
* @returns number
|
|
||||||
*/
|
|
||||||
function getFirstDayOfWeek(localeData: CldrLocaleData) {
|
|
||||||
// The `cldrjs` package does not provide proper types for `supplemental`. The
|
|
||||||
// types are part of the package but embedded incorrectly and not usable.
|
|
||||||
return WEEK_DAYS.indexOf((localeData as any).supplemental.weekData.firstDay());
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google LLC All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
|
||||||
* found in the LICENSE file at https://angular.io/license
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {CldrLocaleData} from './cldr-data';
|
|
||||||
import {fileHeader} from './file-header';
|
|
||||||
import {BaseCurrencies} from './locale-base-currencies';
|
|
||||||
import {generateDayPeriodsSupplementalString} from './locale-extra-file';
|
|
||||||
import {generateBasicLocaleString} from './locale-file';
|
|
||||||
import {getPluralFunction} from './plural-function';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generated the contents for the global locale file
|
|
||||||
*/
|
|
||||||
export function generateLocaleGlobalFile(
|
|
||||||
locale: string, localeData: CldrLocaleData, baseCurrencies: BaseCurrencies) {
|
|
||||||
const basicLocaleData = generateBasicLocaleString(locale, localeData, baseCurrencies);
|
|
||||||
const extraLocaleData = generateDayPeriodsSupplementalString(locale, localeData);
|
|
||||||
const data = basicLocaleData.replace(/\]$/, `, ${extraLocaleData}]`);
|
|
||||||
return `${fileHeader}
|
|
||||||
(function(global) {
|
|
||||||
global.ng = global.ng || {};
|
|
||||||
global.ng.common = global.ng.common || {};
|
|
||||||
global.ng.common.locales = global.ng.common.locales || {};
|
|
||||||
const u = undefined;
|
|
||||||
${getPluralFunction(locale, false)}
|
|
||||||
global.ng.common.locales['${normalizeLocale(locale)}'] = ${data};
|
|
||||||
})(typeof globalThis !== 'undefined' && globalThis || typeof global !== 'undefined' && global || typeof window !== 'undefined' && window);
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* In Angular the locale is referenced by a "normalized" form.
|
|
||||||
*/
|
|
||||||
function normalizeLocale(locale: string): string {
|
|
||||||
return locale.toLowerCase().replace(/_/g, '-');
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google LLC All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
|
||||||
* found in the LICENSE file at https://angular.io/license
|
|
||||||
*/
|
|
||||||
|
|
||||||
const UNDEFINED_PLACEHOLDER = `ɵɵUNDEFINED_PLACEHOLDER_JSON`;
|
|
||||||
const UNDEFINED_PLACEHOLDER_REGEX = new RegExp(`["']${UNDEFINED_PLACEHOLDER}["']`, 'g');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stringifies the given object while preserving `undefined` values which would usually
|
|
||||||
* be transformed into `null` with JSON5. We want to preserve `undefined` because in generated
|
|
||||||
* JavaScript, the `undefined` values are separate from `null`, and `undefined` can be minified
|
|
||||||
* more efficiently. For example in arrays: `[, , someValue]`.
|
|
||||||
*
|
|
||||||
* Note that we do not use `JSON5` or similar formats where properties are not explicitly
|
|
||||||
* wrapped in quotes. Quotes are necessary so that Closure compiler does not accidentally
|
|
||||||
* rename properties. See an example where the currency symbols will be incorrect:
|
|
||||||
* https://closure-compiler.appspot.com/home#code%3D%252F%252F%2520%253D%253DClosureCompiler%253D%253D%250A%252F%252F%2520%2540output_file_name%2520default.js%250A%252F%252F%2520%2540compilation_level%2520ADVANCED_OPTIMIZATIONS%250A%252F%252F%2520%253D%253D%252FClosureCompiler%253D%253D%250A%250Aconst%2520base_currencies%2520%253D%2520%257B%250A%2520%2520ABC%253A%2520'd'%252C%250A%2509USD%253A%2520'x'%252C%250A%257D%253B%250A%250Aconst%2520current_locale_currencies%2520%253D%2520%257B%257D%250A%250Afunction%2520getCurrencySymbol(l)%2520%257B%250A%2520%2520return%2520current_locale_currencies%255Bl%255D%2520%257C%257C%2520base_currencies%255Bl%255D%2520%257C%257C%2520l%250A%257D%250A%250Aconsole.log(getCurrencySymbol('de'))%253B
|
|
||||||
*/
|
|
||||||
export function stringify(value: any) {
|
|
||||||
const result =
|
|
||||||
JSON.stringify(value, ((_, value) => value === undefined ? UNDEFINED_PLACEHOLDER : value));
|
|
||||||
|
|
||||||
UNDEFINED_PLACEHOLDER_REGEX.lastIndex = 0;
|
|
||||||
|
|
||||||
return result.replace(UNDEFINED_PLACEHOLDER_REGEX, 'undefined');
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright Google LLC All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
|
||||||
* found in the LICENSE file at https://angular.io/license
|
|
||||||
*/
|
|
||||||
|
|
||||||
// There are no types available for `cldr`.
|
|
||||||
const cldr = require('cldr');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the plural function for a locale
|
|
||||||
* TODO(ocombe): replace "cldr" extractPluralRuleFunction with our own extraction using "CldrJS"
|
|
||||||
* because the 2 libs can become out of sync if they use different versions of the cldr database
|
|
||||||
*/
|
|
||||||
export function getPluralFunction(locale: string, withTypes = true) {
|
|
||||||
let fn = cldr.extractPluralRuleFunction(locale).toString();
|
|
||||||
|
|
||||||
const numberType = withTypes ? ': number' : '';
|
|
||||||
fn =
|
|
||||||
fn.replace(/function anonymous\(n[^}]+{/g, `function plural(n${numberType})${numberType} {`)
|
|
||||||
// Since our generated plural functions only take numbers, we can eliminate some of
|
|
||||||
// the logic generated by the `cldr` package (to reduce payload size).
|
|
||||||
.replace(/var/g, /let/)
|
|
||||||
.replace(/if\s+\(typeof\s+n\s+===\s+["']string["']\)\s+n\s+=\s+parseInt\(n,\s+10\);/, '');
|
|
||||||
|
|
||||||
// The replacement values must match the `Plural` enum from common.
|
|
||||||
// We do not use the enum directly to avoid depending on that package.
|
|
||||||
return fn.replace(/["']zero["']/, '0')
|
|
||||||
.replace(/["']one["']/, '1')
|
|
||||||
.replace(/["']two["']/, '2')
|
|
||||||
.replace(/["']few["']/, '3')
|
|
||||||
.replace(/["']many["']/, '4')
|
|
||||||
.replace(/["']other["']/, '5');
|
|
||||||
}
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google LLC All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
const path = require('path');
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
extract: gulp => done => {
|
||||||
|
if (!fs.existsSync(path.join(__dirname, 'cldr/cldr-data'))) {
|
||||||
|
throw new Error(`You must run "gulp cldr:download" before you can extract the data`);
|
||||||
|
}
|
||||||
|
const extract = require('./cldr/extract');
|
||||||
|
return extract(gulp, done);
|
||||||
|
},
|
||||||
|
|
||||||
|
download: gulp => done => {
|
||||||
|
const cldrDownloader = require('cldr-data-downloader');
|
||||||
|
const cldrDataFolder = path.join(__dirname, 'cldr/cldr-data');
|
||||||
|
if (fs.existsSync(cldrDataFolder)) {
|
||||||
|
fs.rmdirSync(cldrDataFolder, {recursive: true});
|
||||||
|
} else {
|
||||||
|
fs.mkdirSync(cldrDataFolder);
|
||||||
|
}
|
||||||
|
cldrDownloader(path.join(__dirname, 'cldr/cldr-urls.json'), cldrDataFolder, {}, done);
|
||||||
|
},
|
||||||
|
|
||||||
|
closure: gulp => done => {
|
||||||
|
const {RELATIVE_I18N_DATA_FOLDER} = require('./cldr/extract');
|
||||||
|
// tslint:disable-next-line:no-console
|
||||||
|
console.log(RELATIVE_I18N_DATA_FOLDER, fs.existsSync(RELATIVE_I18N_DATA_FOLDER));
|
||||||
|
if (!fs.existsSync(RELATIVE_I18N_DATA_FOLDER)) {
|
||||||
|
throw new Error(
|
||||||
|
`You must run "gulp cldr:extract" before you can create the closure-locale.ts file`);
|
||||||
|
}
|
||||||
|
const localeAll = require('./cldr/closure');
|
||||||
|
return localeAll(gulp, done);
|
||||||
|
},
|
||||||
|
};
|
|
@ -0,0 +1,86 @@
|
||||||
|
// tslint:disable:file-header
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Npm module for Unicode CLDR JSON data
|
||||||
|
*
|
||||||
|
* @license
|
||||||
|
* Copyright 2013 Rafael Xavier de Souza
|
||||||
|
* Released under the MIT license
|
||||||
|
* https://github.com/rxaviers/cldr-data-npm/blob/master/LICENSE-MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const JSON_EXTENSION = /^(.*)\.json$/;
|
||||||
|
|
||||||
|
const assert = require('assert');
|
||||||
|
const _fs = require('fs');
|
||||||
|
const _path = require('path');
|
||||||
|
|
||||||
|
function argsToArray(arg) {
|
||||||
|
return [].slice.call(arg, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function jsonFiles(dirName) {
|
||||||
|
const fileList = _fs.readdirSync(_path.join(__dirname, 'cldr-data', dirName));
|
||||||
|
|
||||||
|
return fileList.reduce(function(sum, file) {
|
||||||
|
if (JSON_EXTENSION.test(file)) {
|
||||||
|
return sum.concat(file.match(JSON_EXTENSION)[1]);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cldrData(path /*, ...*/) {
|
||||||
|
assert(
|
||||||
|
typeof path === 'string',
|
||||||
|
'must include path (e.g., "main/en/numbers" or "supplemental/likelySubtags")');
|
||||||
|
|
||||||
|
if (arguments.length > 1) {
|
||||||
|
return argsToArray(arguments).reduce(function(sum, path) {
|
||||||
|
sum.push(cldrData(path));
|
||||||
|
return sum;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
return require('./cldr-data/' + path);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mainPathsFor(locales) {
|
||||||
|
return locales.reduce(function(sum, locale) {
|
||||||
|
const mainFiles = jsonFiles(_path.join('main', locale));
|
||||||
|
mainFiles.forEach(function(mainFile) {
|
||||||
|
sum.push(_path.join('main', locale, mainFile));
|
||||||
|
});
|
||||||
|
return sum;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
function supplementalPaths() {
|
||||||
|
const supplementalFiles = jsonFiles('supplemental');
|
||||||
|
|
||||||
|
return supplementalFiles.map(function(supplementalFile) {
|
||||||
|
return _path.join('supplemental', supplementalFile);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(cldrData, 'availableLocales', {
|
||||||
|
get: function() {
|
||||||
|
return cldrData('availableLocales').availableLocales;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cldrData.all = function() {
|
||||||
|
const paths = supplementalPaths().concat(mainPathsFor(this.availableLocales));
|
||||||
|
return cldrData.apply({}, paths);
|
||||||
|
};
|
||||||
|
|
||||||
|
cldrData.entireMainFor = function(locale /*, ...*/) {
|
||||||
|
assert(typeof locale === 'string', 'must include locale (e.g., "en")');
|
||||||
|
return cldrData.apply({}, mainPathsFor(argsToArray(arguments)));
|
||||||
|
};
|
||||||
|
|
||||||
|
cldrData.entireSupplemental = function() {
|
||||||
|
return cldrData.apply({}, supplementalPaths());
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = cldrData;
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"core": [
|
||||||
|
"https://github.com/unicode-cldr/cldr-core/archive/37.0.0.zip",
|
||||||
|
"https://github.com/unicode-cldr/cldr-segments-modern/archive/37.0.0.zip",
|
||||||
|
"https://github.com/unicode-cldr/cldr-dates-full/archive/37.0.0.zip",
|
||||||
|
"https://github.com/unicode-cldr/cldr-cal-buddhist-full/archive/37.0.0.zip",
|
||||||
|
"https://github.com/unicode-cldr/cldr-cal-chinese-full/archive/37.0.0.zip",
|
||||||
|
"https://github.com/unicode-cldr/cldr-cal-coptic-full/archive/37.0.0.zip",
|
||||||
|
"https://github.com/unicode-cldr/cldr-cal-dangi-full/archive/37.0.0.zip",
|
||||||
|
"https://github.com/unicode-cldr/cldr-cal-ethiopic-full/archive/37.0.0.zip",
|
||||||
|
"https://github.com/unicode-cldr/cldr-cal-hebrew-full/archive/37.0.0.zip",
|
||||||
|
"https://github.com/unicode-cldr/cldr-cal-indian-full/archive/37.0.0.zip",
|
||||||
|
"https://github.com/unicode-cldr/cldr-cal-islamic-full/archive/37.0.0.zip",
|
||||||
|
"https://github.com/unicode-cldr/cldr-cal-japanese-full/archive/37.0.0.zip",
|
||||||
|
"https://github.com/unicode-cldr/cldr-cal-persian-full/archive/37.0.0.zip",
|
||||||
|
"https://github.com/unicode-cldr/cldr-cal-roc-full/archive/37.0.0.zip",
|
||||||
|
"https://github.com/unicode-cldr/cldr-localenames-full/archive/37.0.0.zip",
|
||||||
|
"https://github.com/unicode-cldr/cldr-misc-full/archive/37.0.0.zip",
|
||||||
|
"https://github.com/unicode-cldr/cldr-numbers-full/archive/37.0.0.zip",
|
||||||
|
"https://github.com/unicode-cldr/cldr-units-full/archive/37.0.0.zip"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,163 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google LLC All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const yargs = require('yargs').argv;
|
||||||
|
const shelljs = require('shelljs');
|
||||||
|
const {I18N_DATA_FOLDER, RELATIVE_I18N_DATA_FOLDER, HEADER} = require('./extract');
|
||||||
|
const OUTPUT_NAME = `closure-locale.ts`;
|
||||||
|
|
||||||
|
// tslint:disable:no-console
|
||||||
|
module.exports = (gulp, done) => {
|
||||||
|
// the locales used by closure that will be used to generate the closure-locale file
|
||||||
|
// extracted from:
|
||||||
|
// https://github.com/google/closure-library/blob/master/closure/goog/i18n/datetimepatterns.js#L2136
|
||||||
|
let GOOG_LOCALES = [
|
||||||
|
'af', 'am', 'ar', 'ar-DZ', 'az', 'be', 'bg', 'bn', 'br', 'bs',
|
||||||
|
'ca', 'chr', 'cs', 'cy', 'da', 'de', 'de-AT', 'de-CH', 'el', 'en-AU',
|
||||||
|
'en-CA', 'en-GB', 'en-IE', 'en-IN', 'en-SG', 'en-ZA', 'es', 'es-419', 'es-MX', 'es-US',
|
||||||
|
'et', 'eu', 'fa', 'fi', 'fr', 'fr-CA', 'ga', 'gl', 'gsw', 'gu',
|
||||||
|
'haw', 'hi', 'hr', 'hu', 'hy', 'in', 'is', 'it', 'iw', 'ja',
|
||||||
|
'ka', 'kk', 'km', 'kn', 'ko', 'ky', 'ln', 'lo', 'lt', 'lv',
|
||||||
|
'mk', 'ml', 'mn', 'mo', 'mr', 'ms', 'mt', 'my', 'ne', 'nl',
|
||||||
|
'no', 'or', 'pa', 'pl', 'pt', 'pt-PT', 'ro', 'ru', 'sh', 'si',
|
||||||
|
'sk', 'sl', 'sq', 'sr', 'sv', 'sw', 'ta', 'te', 'th', 'tl',
|
||||||
|
'tr', 'uk', 'ur', 'uz', 'vi', 'zh', 'zh-CN', 'zh-HK', 'zh-TW', 'zu'
|
||||||
|
];
|
||||||
|
|
||||||
|
// locale id aliases to support deprecated locale ids used by closure
|
||||||
|
// it maps deprecated ids --> new ids
|
||||||
|
// manually extracted from ./cldr-data/supplemental/aliases.json
|
||||||
|
const ALIASES = {
|
||||||
|
'in': 'id',
|
||||||
|
'iw': 'he',
|
||||||
|
'mo': 'ro-MD',
|
||||||
|
'no': 'nb',
|
||||||
|
'nb': 'no-NO',
|
||||||
|
'sh': 'sr-Latn',
|
||||||
|
'tl': 'fil',
|
||||||
|
'pt': 'pt-BR',
|
||||||
|
'zh-CN': 'zh-Hans-CN',
|
||||||
|
'zh-Hans-CN': 'zh-Hans',
|
||||||
|
'zh-HK': 'zh-Hant-HK',
|
||||||
|
'zh-TW': 'zh-Hant-TW',
|
||||||
|
'zh-Hant-TW': 'zh-Hant',
|
||||||
|
};
|
||||||
|
|
||||||
|
if (yargs.locales) {
|
||||||
|
GOOG_LOCALES = yargs.locales.split(',');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Writing file ${I18N_DATA_FOLDER}/${OUTPUT_NAME}`);
|
||||||
|
fs.writeFileSync(
|
||||||
|
`${RELATIVE_I18N_DATA_FOLDER}/${OUTPUT_NAME}`, generateAllLocalesFile(GOOG_LOCALES, ALIASES));
|
||||||
|
|
||||||
|
console.log(`Formatting ${I18N_DATA_FOLDER}/${OUTPUT_NAME}..."`);
|
||||||
|
shelljs.exec(`yarn clang-format -i ${I18N_DATA_FOLDER}/${OUTPUT_NAME}`, {silent: true});
|
||||||
|
done();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a file that contains all locale to import for closure.
|
||||||
|
* Tree shaking will only keep the data for the `goog.LOCALE` locale.
|
||||||
|
*/
|
||||||
|
function generateAllLocalesFile(LOCALES, ALIASES) {
|
||||||
|
const existingLocalesAliases = {};
|
||||||
|
const existingLocalesData = {};
|
||||||
|
|
||||||
|
// for each locale, get the data and the list of equivalent locales
|
||||||
|
LOCALES.forEach(locale => {
|
||||||
|
const eqLocales = new Set();
|
||||||
|
eqLocales.add(locale);
|
||||||
|
if (locale.match(/-/)) {
|
||||||
|
eqLocales.add(locale.replace(/-/g, '_'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for aliases
|
||||||
|
const alias = ALIASES[locale];
|
||||||
|
if (alias) {
|
||||||
|
eqLocales.add(alias);
|
||||||
|
|
||||||
|
if (alias.match(/-/)) {
|
||||||
|
eqLocales.add(alias.replace(/-/g, '_'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// to avoid duplicated "case" we regroup all locales in the same "case"
|
||||||
|
// the simplest way to do that is to have alias aliases
|
||||||
|
// e.g. 'no' --> 'nb', 'nb' --> 'no-NO'
|
||||||
|
// which means that we'll have 'no', 'nb' and 'no-NO' in the same "case"
|
||||||
|
const aliasKeys = Object.keys(ALIASES);
|
||||||
|
for (let i = 0; i < aliasKeys.length; i++) {
|
||||||
|
const aliasValue = ALIASES[alias];
|
||||||
|
if (aliasKeys.indexOf(alias) !== -1 && !eqLocales.has(aliasValue)) {
|
||||||
|
eqLocales.add(aliasValue);
|
||||||
|
|
||||||
|
if (aliasValue.match(/-/)) {
|
||||||
|
eqLocales.add(aliasValue.replace(/-/g, '_'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let l of eqLocales) {
|
||||||
|
// find the existing content file
|
||||||
|
const path = `${RELATIVE_I18N_DATA_FOLDER}/${l}.ts`;
|
||||||
|
if (fs.existsSync(`${RELATIVE_I18N_DATA_FOLDER}/${l}.ts`)) {
|
||||||
|
const localeName = formatLocale(locale);
|
||||||
|
existingLocalesData[locale] =
|
||||||
|
fs.readFileSync(path, 'utf8')
|
||||||
|
.replace(`${HEADER}\n`, '')
|
||||||
|
.replace('export default ', `export const locale_${localeName} = `)
|
||||||
|
.replace('function plural', `function plural_${localeName}`)
|
||||||
|
.replace(/,(\n | )plural/, `, plural_${localeName}`)
|
||||||
|
.replace('const u = undefined;\n\n', '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
existingLocalesAliases[locale] = eqLocales;
|
||||||
|
});
|
||||||
|
|
||||||
|
function generateCases(locale) {
|
||||||
|
let str = '';
|
||||||
|
let locales = [];
|
||||||
|
const eqLocales = existingLocalesAliases[locale];
|
||||||
|
for (let l of eqLocales) {
|
||||||
|
str += `case '${l}':\n`;
|
||||||
|
locales.push(`'${l}'`);
|
||||||
|
}
|
||||||
|
let localesStr = '[' + locales.join(',') + ']';
|
||||||
|
|
||||||
|
str += ` l = locale_${formatLocale(locale)};
|
||||||
|
locales = ${localesStr};
|
||||||
|
break;\n`;
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatLocale(locale) {
|
||||||
|
return locale.replace(/-/g, '_');
|
||||||
|
}
|
||||||
|
// clang-format off
|
||||||
|
return `${HEADER}
|
||||||
|
import {registerLocaleData} from '../src/i18n/locale_data';
|
||||||
|
|
||||||
|
const u = undefined;
|
||||||
|
|
||||||
|
${LOCALES.map(locale => `${existingLocalesData[locale]}`).join('\n')}
|
||||||
|
|
||||||
|
let l: any;
|
||||||
|
let locales: string[] = [];
|
||||||
|
|
||||||
|
switch (goog.LOCALE) {
|
||||||
|
${LOCALES.map(locale => generateCases(locale)).join('')}}
|
||||||
|
|
||||||
|
if(l) {
|
||||||
|
locales.forEach(locale => registerLocaleData(l, locale));
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
// clang-format on
|
||||||
|
}
|
|
@ -0,0 +1,632 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google LLC All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const stringify = require('./util').stringify;
|
||||||
|
// used to extract plural rules
|
||||||
|
const cldr = require('cldr');
|
||||||
|
// used to extract all other cldr data
|
||||||
|
const cldrJs = require('cldrjs');
|
||||||
|
// used to call to clang-format
|
||||||
|
const shelljs = require('shelljs');
|
||||||
|
|
||||||
|
const COMMON_PACKAGE = 'packages/common';
|
||||||
|
const CORE_PACKAGE = 'packages/core';
|
||||||
|
const I18N_FOLDER = `${COMMON_PACKAGE}/src/i18n`;
|
||||||
|
const I18N_CORE_FOLDER = `${CORE_PACKAGE}/src/i18n`;
|
||||||
|
const I18N_DATA_FOLDER = `${COMMON_PACKAGE}/locales`;
|
||||||
|
const I18N_DATA_EXTRA_FOLDER = `${I18N_DATA_FOLDER}/extra`;
|
||||||
|
const I18N_GLOBAL_FOLDER = `${I18N_DATA_FOLDER}/global`;
|
||||||
|
const RELATIVE_I18N_FOLDER = path.resolve(__dirname, `../../../${I18N_FOLDER}`);
|
||||||
|
const RELATIVE_I18N_CORE_FOLDER = path.resolve(__dirname, `../../../${I18N_CORE_FOLDER}`);
|
||||||
|
const RELATIVE_I18N_DATA_FOLDER = path.resolve(__dirname, `../../../${I18N_DATA_FOLDER}`);
|
||||||
|
const RELATIVE_I18N_DATA_EXTRA_FOLDER =
|
||||||
|
path.resolve(__dirname, `../../../${I18N_DATA_EXTRA_FOLDER}`);
|
||||||
|
const RELATIVE_I18N_GLOBAL_FOLDER = path.resolve(__dirname, `../../../${I18N_GLOBAL_FOLDER}`);
|
||||||
|
const DEFAULT_RULE = 'function anonymous(n) {\nreturn"other"\n}';
|
||||||
|
const EMPTY_RULE = 'function anonymous(n) {\n\n}';
|
||||||
|
const WEEK_DAYS = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
|
||||||
|
const HEADER = `/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google LLC All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
// THIS CODE IS GENERATED - DO NOT MODIFY
|
||||||
|
// See angular/tools/gulp-tasks/cldr/extract.js
|
||||||
|
`;
|
||||||
|
|
||||||
|
// tslint:disable:no-console
|
||||||
|
module.exports = (gulp, done) => {
|
||||||
|
const cldrData = require('./cldr-data');
|
||||||
|
const LOCALES = cldrData.availableLocales;
|
||||||
|
|
||||||
|
console.log(`Loading CLDR data...`);
|
||||||
|
cldrJs.load(cldrData.all().concat(cldrData('scriptMetadata')));
|
||||||
|
|
||||||
|
console.log(`Writing locale files`);
|
||||||
|
if (!fs.existsSync(RELATIVE_I18N_FOLDER)) {
|
||||||
|
fs.mkdirSync(RELATIVE_I18N_FOLDER);
|
||||||
|
}
|
||||||
|
if (!fs.existsSync(RELATIVE_I18N_DATA_FOLDER)) {
|
||||||
|
fs.mkdirSync(RELATIVE_I18N_DATA_FOLDER);
|
||||||
|
}
|
||||||
|
if (!fs.existsSync(RELATIVE_I18N_DATA_EXTRA_FOLDER)) {
|
||||||
|
fs.mkdirSync(RELATIVE_I18N_DATA_EXTRA_FOLDER);
|
||||||
|
}
|
||||||
|
if (!fs.existsSync(RELATIVE_I18N_GLOBAL_FOLDER)) {
|
||||||
|
fs.mkdirSync(RELATIVE_I18N_GLOBAL_FOLDER);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Writing file ${I18N_FOLDER}/currencies.ts`);
|
||||||
|
fs.writeFileSync(`${RELATIVE_I18N_FOLDER}/currencies.ts`, generateCurrenciesFile());
|
||||||
|
|
||||||
|
const baseCurrencies = generateBaseCurrencies(new cldrJs('en'));
|
||||||
|
// additional "en" file that will be included in common
|
||||||
|
console.log(`Writing file ${I18N_CORE_FOLDER}/locale_en.ts`);
|
||||||
|
const localeEnFile = generateLocale('en', new cldrJs('en'), baseCurrencies);
|
||||||
|
fs.writeFileSync(`${RELATIVE_I18N_CORE_FOLDER}/locale_en.ts`, localeEnFile);
|
||||||
|
|
||||||
|
LOCALES.forEach((locale, index) => {
|
||||||
|
const localeData = new cldrJs(locale);
|
||||||
|
|
||||||
|
console.log(`${index + 1}/${LOCALES.length}`);
|
||||||
|
console.log(`\t${I18N_DATA_FOLDER}/${locale}.ts`);
|
||||||
|
fs.writeFileSync(
|
||||||
|
`${RELATIVE_I18N_DATA_FOLDER}/${locale}.ts`,
|
||||||
|
locale === 'en' ? localeEnFile : generateLocale(locale, localeData, baseCurrencies));
|
||||||
|
console.log(`\t${I18N_DATA_EXTRA_FOLDER}/${locale}.ts`);
|
||||||
|
fs.writeFileSync(
|
||||||
|
`${RELATIVE_I18N_DATA_EXTRA_FOLDER}/${locale}.ts`, generateLocaleExtra(locale, localeData));
|
||||||
|
console.log(`\t${I18N_GLOBAL_FOLDER}/${locale}.js`);
|
||||||
|
fs.writeFileSync(
|
||||||
|
`${RELATIVE_I18N_GLOBAL_FOLDER}/${locale}.js`,
|
||||||
|
generateGlobalLocale(
|
||||||
|
locale, locale === 'en' ? new cldrJs('en') : localeData, baseCurrencies));
|
||||||
|
});
|
||||||
|
console.log(`${LOCALES.length} locale files generated.`);
|
||||||
|
|
||||||
|
console.log(`All i18n cldr files have been generated, formatting files..."`);
|
||||||
|
shelljs.exec(
|
||||||
|
`yarn clang-format -i ${I18N_DATA_FOLDER}/**/*.ts ${I18N_DATA_FOLDER}/*.ts ${
|
||||||
|
I18N_FOLDER}/currencies.ts ${I18N_CORE_FOLDER}/locale_en.ts ${I18N_GLOBAL_FOLDER}/*.js`,
|
||||||
|
{silent: true});
|
||||||
|
done();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate contents for the basic locale data file
|
||||||
|
*/
|
||||||
|
function generateLocale(locale, localeData, baseCurrencies) {
|
||||||
|
return `${HEADER}
|
||||||
|
const u = undefined;
|
||||||
|
|
||||||
|
${getPluralFunction(locale)}
|
||||||
|
|
||||||
|
export default ${generateBasicLocaleString(locale, localeData, baseCurrencies)};
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the contents for the extra data file
|
||||||
|
*/
|
||||||
|
function generateLocaleExtra(locale, localeData) {
|
||||||
|
return `${HEADER}
|
||||||
|
const u = undefined;
|
||||||
|
|
||||||
|
export default ${generateDayPeriodsSupplementalString(locale, localeData)};
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generated the contents for the global locale file
|
||||||
|
*/
|
||||||
|
function generateGlobalLocale(locale, localeData, baseCurrencies) {
|
||||||
|
const basicLocaleData = generateBasicLocaleString(locale, localeData, baseCurrencies);
|
||||||
|
const extraLocaleData = generateDayPeriodsSupplementalString(locale, localeData);
|
||||||
|
const data = basicLocaleData.replace(/\]$/, `, ${extraLocaleData}]`);
|
||||||
|
return `${HEADER}
|
||||||
|
(function(global) {
|
||||||
|
global.ng = global.ng || {};
|
||||||
|
global.ng.common = global.ng.common || {};
|
||||||
|
global.ng.common.locales = global.ng.common.locales || {};
|
||||||
|
const u = undefined;
|
||||||
|
${getPluralFunction(locale, false)}
|
||||||
|
global.ng.common.locales['${normalizeLocale(locale)}'] = ${data};
|
||||||
|
})(typeof globalThis !== 'undefined' && globalThis || typeof global !== 'undefined' && global || typeof window !== 'undefined' && window);
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collect up the basic locale data [ localeId, dateTime, number, currency, pluralCase ].
|
||||||
|
*/
|
||||||
|
function generateBasicLocaleString(locale, localeData, baseCurrencies) {
|
||||||
|
let data = stringify(
|
||||||
|
[
|
||||||
|
locale,
|
||||||
|
...getDateTimeTranslations(localeData),
|
||||||
|
...getDateTimeSettings(localeData),
|
||||||
|
...getNumberSettings(localeData),
|
||||||
|
...getCurrencySettings(locale, localeData),
|
||||||
|
generateLocaleCurrencies(localeData, baseCurrencies),
|
||||||
|
getDirectionality(localeData),
|
||||||
|
],
|
||||||
|
true)
|
||||||
|
// We remove "undefined" added by spreading arrays when there is no value
|
||||||
|
.replace(/undefined/g, 'u');
|
||||||
|
|
||||||
|
// adding plural function after, because we don't want it as a string
|
||||||
|
data = data.replace(/\]$/, ', plural]');
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collect up the day period rules, and extended day period data.
|
||||||
|
*/
|
||||||
|
function generateDayPeriodsSupplementalString(locale, localeData) {
|
||||||
|
const dayPeriods = getDayPeriodsNoAmPm(localeData);
|
||||||
|
const dayPeriodRules = getDayPeriodRules(localeData);
|
||||||
|
|
||||||
|
let dayPeriodsSupplemental = [];
|
||||||
|
if (Object.keys(dayPeriods.format.narrow).length) {
|
||||||
|
const keys = Object.keys(dayPeriods.format.narrow);
|
||||||
|
|
||||||
|
if (keys.length !== Object.keys(dayPeriodRules).length) {
|
||||||
|
throw new Error(`Error: locale ${locale} has not the correct number of day period rules`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const dayPeriodsFormat = removeDuplicates([
|
||||||
|
objectValues(dayPeriods.format.narrow), objectValues(dayPeriods.format.abbreviated),
|
||||||
|
objectValues(dayPeriods.format.wide)
|
||||||
|
]);
|
||||||
|
|
||||||
|
const dayPeriodsStandalone = removeDuplicates([
|
||||||
|
objectValues(dayPeriods['stand-alone'].narrow),
|
||||||
|
objectValues(dayPeriods['stand-alone'].abbreviated),
|
||||||
|
objectValues(dayPeriods['stand-alone'].wide)
|
||||||
|
]);
|
||||||
|
|
||||||
|
const rules = keys.map(key => dayPeriodRules[key]);
|
||||||
|
dayPeriodsSupplemental = [...removeDuplicates([dayPeriodsFormat, dayPeriodsStandalone]), rules];
|
||||||
|
}
|
||||||
|
return stringify(dayPeriodsSupplemental).replace(/undefined/g, 'u');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a list of currencies to be used as a based for other currencies
|
||||||
|
* e.g.: {'ARS': [, '$'], 'AUD': ['A$', '$'], ...}
|
||||||
|
*/
|
||||||
|
function generateBaseCurrencies(localeData, addDigits) {
|
||||||
|
const currenciesData = localeData.main('numbers/currencies');
|
||||||
|
const fractions = new cldrJs('en').get(`supplemental/currencyData/fractions`);
|
||||||
|
const currencies = {};
|
||||||
|
Object.keys(currenciesData).forEach(key => {
|
||||||
|
let symbolsArray = [];
|
||||||
|
const symbol = currenciesData[key].symbol;
|
||||||
|
const symbolNarrow = currenciesData[key]['symbol-alt-narrow'];
|
||||||
|
if (symbol && symbol !== key) {
|
||||||
|
symbolsArray.push(symbol);
|
||||||
|
}
|
||||||
|
if (symbolNarrow && symbolNarrow !== symbol) {
|
||||||
|
if (symbolsArray.length > 0) {
|
||||||
|
symbolsArray.push(symbolNarrow);
|
||||||
|
} else {
|
||||||
|
symbolsArray = [undefined, symbolNarrow];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (addDigits && fractions[key] && fractions[key]['_digits']) {
|
||||||
|
const digits = parseInt(fractions[key]['_digits'], 10);
|
||||||
|
if (symbolsArray.length === 2) {
|
||||||
|
symbolsArray.push(digits);
|
||||||
|
} else if (symbolsArray.length === 1) {
|
||||||
|
symbolsArray = [...symbolsArray, undefined, digits];
|
||||||
|
} else {
|
||||||
|
symbolsArray = [undefined, undefined, digits];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (symbolsArray.length > 0) {
|
||||||
|
currencies[key] = symbolsArray;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return currencies;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To minimize the file even more, we only output the differences compared to the base currency
|
||||||
|
*/
|
||||||
|
function generateLocaleCurrencies(localeData, baseCurrencies) {
|
||||||
|
const currenciesData = localeData.main('numbers/currencies');
|
||||||
|
const currencies = {};
|
||||||
|
Object.keys(currenciesData).forEach(code => {
|
||||||
|
let symbolsArray = [];
|
||||||
|
const symbol = currenciesData[code].symbol;
|
||||||
|
const symbolNarrow = currenciesData[code]['symbol-alt-narrow'];
|
||||||
|
if (symbol && symbol !== code) {
|
||||||
|
symbolsArray.push(symbol);
|
||||||
|
}
|
||||||
|
if (symbolNarrow && symbolNarrow !== symbol) {
|
||||||
|
if (symbolsArray.length > 0) {
|
||||||
|
symbolsArray.push(symbolNarrow);
|
||||||
|
} else {
|
||||||
|
symbolsArray = [undefined, symbolNarrow];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if locale data are different, set the value
|
||||||
|
if ((baseCurrencies[code] || []).toString() !== symbolsArray.toString()) {
|
||||||
|
currencies[code] = symbolsArray;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return currencies;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a file that contains the list of currencies and their symbols
|
||||||
|
*/
|
||||||
|
function generateCurrenciesFile() {
|
||||||
|
const baseCurrencies = generateBaseCurrencies(new cldrJs('en'), true);
|
||||||
|
|
||||||
|
return `${HEADER}
|
||||||
|
export type CurrenciesSymbols = [string] | [string | undefined, string];
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
export const CURRENCIES_EN: {[code: string]: CurrenciesSymbols | [string | undefined, string | undefined, number]} = ${
|
||||||
|
stringify(baseCurrencies, true)};
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns data for the chosen day periods
|
||||||
|
* @returns {
|
||||||
|
* format: {narrow / abbreviated / wide: [...]},
|
||||||
|
* stand-alone: {narrow / abbreviated / wide: [...]}
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
function getDayPeriods(localeData, dayPeriodsList) {
|
||||||
|
const dayPeriods = localeData.main(`dates/calendars/gregorian/dayPeriods`);
|
||||||
|
const result = {};
|
||||||
|
// cleaning up unused keys
|
||||||
|
Object.keys(dayPeriods).forEach(key1 => { // format / stand-alone
|
||||||
|
result[key1] = {};
|
||||||
|
Object.keys(dayPeriods[key1]).forEach(key2 => { // narrow / abbreviated / wide
|
||||||
|
result[key1][key2] = {};
|
||||||
|
Object.keys(dayPeriods[key1][key2]).forEach(key3 => {
|
||||||
|
if (dayPeriodsList.indexOf(key3) !== -1) {
|
||||||
|
result[key1][key2][key3] = dayPeriods[key1][key2][key3];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the basic day periods (am/pm)
|
||||||
|
*/
|
||||||
|
function getDayPeriodsAmPm(localeData) {
|
||||||
|
return getDayPeriods(localeData, ['am', 'pm']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the extra day periods (without am/pm)
|
||||||
|
*/
|
||||||
|
function getDayPeriodsNoAmPm(localeData) {
|
||||||
|
return getDayPeriods(localeData, [
|
||||||
|
'noon', 'midnight', 'morning1', 'morning2', 'afternoon1', 'afternoon2', 'evening1', 'evening2',
|
||||||
|
'night1', 'night2'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns date-related translations for a locale
|
||||||
|
* @returns [ dayPeriodsFormat, dayPeriodsStandalone, daysFormat, dayStandalone, monthsFormat,
|
||||||
|
* monthsStandalone, eras ]
|
||||||
|
* each value: [ narrow, abbreviated, wide, short? ]
|
||||||
|
*/
|
||||||
|
function getDateTimeTranslations(localeData) {
|
||||||
|
const dayNames = localeData.main(`dates/calendars/gregorian/days`);
|
||||||
|
const monthNames = localeData.main(`dates/calendars/gregorian/months`);
|
||||||
|
const erasNames = localeData.main(`dates/calendars/gregorian/eras`);
|
||||||
|
const dayPeriods = getDayPeriodsAmPm(localeData);
|
||||||
|
|
||||||
|
const dayPeriodsFormat = removeDuplicates([
|
||||||
|
objectValues(dayPeriods.format.narrow), objectValues(dayPeriods.format.abbreviated),
|
||||||
|
objectValues(dayPeriods.format.wide)
|
||||||
|
]);
|
||||||
|
|
||||||
|
const dayPeriodsStandalone = removeDuplicates([
|
||||||
|
objectValues(dayPeriods['stand-alone'].narrow),
|
||||||
|
objectValues(dayPeriods['stand-alone'].abbreviated),
|
||||||
|
objectValues(dayPeriods['stand-alone'].wide)
|
||||||
|
]);
|
||||||
|
|
||||||
|
const daysFormat = removeDuplicates([
|
||||||
|
objectValues(dayNames.format.narrow), objectValues(dayNames.format.abbreviated),
|
||||||
|
objectValues(dayNames.format.wide), objectValues(dayNames.format.short)
|
||||||
|
]);
|
||||||
|
|
||||||
|
const daysStandalone = removeDuplicates([
|
||||||
|
objectValues(dayNames['stand-alone'].narrow), objectValues(dayNames['stand-alone'].abbreviated),
|
||||||
|
objectValues(dayNames['stand-alone'].wide), objectValues(dayNames['stand-alone'].short)
|
||||||
|
]);
|
||||||
|
|
||||||
|
const monthsFormat = removeDuplicates([
|
||||||
|
objectValues(monthNames.format.narrow), objectValues(monthNames.format.abbreviated),
|
||||||
|
objectValues(monthNames.format.wide)
|
||||||
|
]);
|
||||||
|
|
||||||
|
const monthsStandalone = removeDuplicates([
|
||||||
|
objectValues(monthNames['stand-alone'].narrow),
|
||||||
|
objectValues(monthNames['stand-alone'].abbreviated),
|
||||||
|
objectValues(monthNames['stand-alone'].wide)
|
||||||
|
]);
|
||||||
|
|
||||||
|
const eras = removeDuplicates([
|
||||||
|
[erasNames.eraNarrow['0'], erasNames.eraNarrow['1']],
|
||||||
|
[erasNames.eraAbbr['0'], erasNames.eraAbbr['1']],
|
||||||
|
[erasNames.eraNames['0'], erasNames.eraNames['1']]
|
||||||
|
]);
|
||||||
|
|
||||||
|
const dateTimeTranslations = [
|
||||||
|
...removeDuplicates([dayPeriodsFormat, dayPeriodsStandalone]),
|
||||||
|
...removeDuplicates([daysFormat, daysStandalone]),
|
||||||
|
...removeDuplicates([monthsFormat, monthsStandalone]), eras
|
||||||
|
];
|
||||||
|
|
||||||
|
return dateTimeTranslations;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns date, time and dateTime formats for a locale
|
||||||
|
* @returns [dateFormats, timeFormats, dateTimeFormats]
|
||||||
|
* each format: [ short, medium, long, full ]
|
||||||
|
*/
|
||||||
|
function getDateTimeFormats(localeData) {
|
||||||
|
function getFormats(data) {
|
||||||
|
return removeDuplicates([
|
||||||
|
data.short._value || data.short, data.medium._value || data.medium,
|
||||||
|
data.long._value || data.long, data.full._value || data.full
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const dateFormats = localeData.main('dates/calendars/gregorian/dateFormats');
|
||||||
|
const timeFormats = localeData.main('dates/calendars/gregorian/timeFormats');
|
||||||
|
const dateTimeFormats = localeData.main('dates/calendars/gregorian/dateTimeFormats');
|
||||||
|
|
||||||
|
return [getFormats(dateFormats), getFormats(timeFormats), getFormats(dateTimeFormats)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns day period rules for a locale
|
||||||
|
* @returns string[]
|
||||||
|
*/
|
||||||
|
function getDayPeriodRules(localeData) {
|
||||||
|
const dayPeriodRules =
|
||||||
|
localeData.get(`supplemental/dayPeriodRuleSet/${localeData.attributes.language}`);
|
||||||
|
const rules = {};
|
||||||
|
if (dayPeriodRules) {
|
||||||
|
Object.keys(dayPeriodRules).forEach(key => {
|
||||||
|
if (dayPeriodRules[key]._at) {
|
||||||
|
rules[key] = dayPeriodRules[key]._at;
|
||||||
|
} else {
|
||||||
|
rules[key] = [dayPeriodRules[key]._from, dayPeriodRules[key]._before];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the first day of the week, based on US week days
|
||||||
|
* @returns number
|
||||||
|
*/
|
||||||
|
function getFirstDayOfWeek(localeData) {
|
||||||
|
return WEEK_DAYS.indexOf(localeData.supplemental.weekData.firstDay());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns week-end range for a locale, based on US week days
|
||||||
|
* @returns [number, number]
|
||||||
|
*/
|
||||||
|
function getWeekendRange(localeData) {
|
||||||
|
const startDay =
|
||||||
|
localeData.get(`supplemental/weekData/weekendStart/${localeData.attributes.territory}`) ||
|
||||||
|
localeData.get('supplemental/weekData/weekendStart/001');
|
||||||
|
const endDay =
|
||||||
|
localeData.get(`supplemental/weekData/weekendEnd/${localeData.attributes.territory}`) ||
|
||||||
|
localeData.get('supplemental/weekData/weekendEnd/001');
|
||||||
|
return [WEEK_DAYS.indexOf(startDay), WEEK_DAYS.indexOf(endDay)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns dateTime data for a locale
|
||||||
|
* @returns [ firstDayOfWeek, weekendRange, formats ]
|
||||||
|
*/
|
||||||
|
function getDateTimeSettings(localeData) {
|
||||||
|
return [
|
||||||
|
getFirstDayOfWeek(localeData), getWeekendRange(localeData), ...getDateTimeFormats(localeData)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number symbols and formats for a locale
|
||||||
|
* @returns [ symbols, formats ]
|
||||||
|
* symbols: [ decimal, group, list, percentSign, plusSign, minusSign, exponential,
|
||||||
|
* superscriptingExponent, perMille, infinity, nan, timeSeparator, currencyDecimal?, currencyGroup?
|
||||||
|
* ]
|
||||||
|
* formats: [ currency, decimal, percent, scientific ]
|
||||||
|
*/
|
||||||
|
function getNumberSettings(localeData) {
|
||||||
|
const decimalFormat = localeData.main('numbers/decimalFormats-numberSystem-latn/standard');
|
||||||
|
const percentFormat = localeData.main('numbers/percentFormats-numberSystem-latn/standard');
|
||||||
|
const scientificFormat = localeData.main('numbers/scientificFormats-numberSystem-latn/standard');
|
||||||
|
const currencyFormat = localeData.main('numbers/currencyFormats-numberSystem-latn/standard');
|
||||||
|
const symbols = localeData.main('numbers/symbols-numberSystem-latn');
|
||||||
|
const symbolValues = [
|
||||||
|
symbols.decimal,
|
||||||
|
symbols.group,
|
||||||
|
symbols.list,
|
||||||
|
symbols.percentSign,
|
||||||
|
symbols.plusSign,
|
||||||
|
symbols.minusSign,
|
||||||
|
symbols.exponential,
|
||||||
|
symbols.superscriptingExponent,
|
||||||
|
symbols.perMille,
|
||||||
|
symbols.infinity,
|
||||||
|
symbols.nan,
|
||||||
|
symbols.timeSeparator,
|
||||||
|
];
|
||||||
|
|
||||||
|
if (symbols.currencyDecimal || symbols.currencyGroup) {
|
||||||
|
symbolValues.push(symbols.currencyDecimal);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (symbols.currencyGroup) {
|
||||||
|
symbolValues.push(symbols.currencyGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [symbolValues, [decimalFormat, percentFormat, currencyFormat, scientificFormat]];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the currency code, symbol and name for a locale
|
||||||
|
* @returns [ code, symbol, name ]
|
||||||
|
*/
|
||||||
|
function getCurrencySettings(locale, localeData) {
|
||||||
|
const currencyInfo = localeData.main(`numbers/currencies`);
|
||||||
|
let currentCurrency = '';
|
||||||
|
|
||||||
|
// find the currency currently used in this country
|
||||||
|
const currencies =
|
||||||
|
localeData.get(`supplemental/currencyData/region/${localeData.attributes.territory}`) ||
|
||||||
|
localeData.get(
|
||||||
|
`supplemental/currencyData/region/${localeData.attributes.language.toUpperCase()}`);
|
||||||
|
|
||||||
|
if (currencies) {
|
||||||
|
currencies.some(currency => {
|
||||||
|
const keys = Object.keys(currency);
|
||||||
|
return keys.some(key => {
|
||||||
|
if (currency[key]._from && !currency[key]._to) {
|
||||||
|
return currentCurrency = key;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!currentCurrency) {
|
||||||
|
throw new Error(`Unable to find currency for locale "${locale}"`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let currencySettings = [undefined, undefined, undefined];
|
||||||
|
|
||||||
|
if (currentCurrency) {
|
||||||
|
currencySettings = [
|
||||||
|
currentCurrency, currencyInfo[currentCurrency].symbol,
|
||||||
|
currencyInfo[currentCurrency].displayName
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return currencySettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the writing direction for a locale
|
||||||
|
* @returns 'rtl' | 'ltr'
|
||||||
|
*/
|
||||||
|
function getDirectionality(localeData) {
|
||||||
|
const rtl = localeData.get('scriptMetadata/{script}/rtl');
|
||||||
|
return rtl === 'YES' ? 'rtl' : 'ltr';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms a string into a regexp
|
||||||
|
*/
|
||||||
|
function toRegExp(s) {
|
||||||
|
return new RegExp(s.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'), 'g');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the plural function for a locale
|
||||||
|
* todo(ocombe): replace "cldr" extractPluralRuleFunction with our own extraction using "CldrJS"
|
||||||
|
* because the 2 libs can become out of sync if they use different versions of the cldr database
|
||||||
|
*/
|
||||||
|
function getPluralFunction(locale, withTypes = true) {
|
||||||
|
let fn = cldr.extractPluralRuleFunction(locale).toString();
|
||||||
|
|
||||||
|
if (fn === EMPTY_RULE) {
|
||||||
|
fn = DEFAULT_RULE;
|
||||||
|
}
|
||||||
|
|
||||||
|
const numberType = withTypes ? ': number' : '';
|
||||||
|
fn = fn.replace(/function anonymous\(n[^}]+{/g, `function plural(n${numberType})${numberType} {`)
|
||||||
|
.replace(toRegExp('var'), 'let')
|
||||||
|
.replace(toRegExp('if(typeof n==="string")n=parseInt(n,10);'), '')
|
||||||
|
.replace(toRegExp('\n}'), ';\n}');
|
||||||
|
|
||||||
|
// The replacement values must match the `Plural` enum from common.
|
||||||
|
// We do not use the enum directly to avoid depending on that package.
|
||||||
|
return fn.replace(toRegExp('"zero"'), ' 0')
|
||||||
|
.replace(toRegExp('"one"'), ' 1')
|
||||||
|
.replace(toRegExp('"two"'), ' 2')
|
||||||
|
.replace(toRegExp('"few"'), ' 3')
|
||||||
|
.replace(toRegExp('"many"'), ' 4')
|
||||||
|
.replace(toRegExp('"other"'), ' 5');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an array of values from an object
|
||||||
|
*/
|
||||||
|
function objectValues(obj) {
|
||||||
|
return Object.keys(obj).map(key => obj[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To create smaller locale files, we remove duplicated data.
|
||||||
|
* To be make this work we need to store similar data in arrays, if some value in an array
|
||||||
|
* is undefined, we can take the previous defined value instead, because it means that it has
|
||||||
|
* been deduplicated.
|
||||||
|
* e.g.: [x, y, undefined, z, undefined, undefined]
|
||||||
|
* The first undefined is equivalent to y, the second and third are equivalent to z
|
||||||
|
* Note that the first value in an array is always defined.
|
||||||
|
*
|
||||||
|
* Also since we need to know which data is assumed similar, it is important that we store those
|
||||||
|
* similar data in arrays to mark the delimitation between values that have different meanings
|
||||||
|
* (e.g. months and days).
|
||||||
|
*
|
||||||
|
* For further size improvements, "undefined" values will be replaced by a constant in the arrays
|
||||||
|
* as the last step of the file generation (in generateLocale and generateLocaleExtra).
|
||||||
|
* e.g.: [x, y, undefined, z, undefined, undefined] will be [x, y, u, z, u, u]
|
||||||
|
*/
|
||||||
|
function removeDuplicates(data) {
|
||||||
|
const dedup = [data[0]];
|
||||||
|
for (let i = 1; i < data.length; i++) {
|
||||||
|
if (stringify(data[i]) !== stringify(data[i - 1])) {
|
||||||
|
dedup.push(data[i]);
|
||||||
|
} else {
|
||||||
|
dedup.push(undefined);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dedup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In Angular the locale is referenced by a "normalized" form.
|
||||||
|
*/
|
||||||
|
function normalizeLocale(locale) {
|
||||||
|
return locale.toLowerCase().replace(/_/g, '-');
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.I18N_FOLDER = I18N_FOLDER;
|
||||||
|
module.exports.I18N_DATA_FOLDER = I18N_DATA_FOLDER;
|
||||||
|
module.exports.RELATIVE_I18N_DATA_FOLDER = RELATIVE_I18N_DATA_FOLDER;
|
||||||
|
module.exports.HEADER = HEADER;
|
|
@ -0,0 +1,182 @@
|
||||||
|
// tslint:disable:file-header
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like JSON.stringify, but without double quotes around keys, and without null instead of undefined
|
||||||
|
* values
|
||||||
|
* Based on https://github.com/json5/json5/blob/master/lib/json5.js
|
||||||
|
* Use option "quoteKeys" to preserve quotes for keys
|
||||||
|
*/
|
||||||
|
module.exports.stringify = function(obj, quoteKeys) {
|
||||||
|
var getReplacedValueOrUndefined = function(holder, key) {
|
||||||
|
var value = holder[key];
|
||||||
|
|
||||||
|
// Replace the value with its toJSON value first, if possible
|
||||||
|
if (value && value.toJSON && typeof value.toJSON === 'function') {
|
||||||
|
value = value.toJSON();
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
function isWordChar(c) {
|
||||||
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') ||
|
||||||
|
c === '_' || c === '$';
|
||||||
|
}
|
||||||
|
|
||||||
|
function isWordStart(c) {
|
||||||
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c === '_' || c === '$';
|
||||||
|
}
|
||||||
|
|
||||||
|
function isWord(key) {
|
||||||
|
if (typeof key !== 'string') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!isWordStart(key[0])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var i = 1, length = key.length;
|
||||||
|
while (i < length) {
|
||||||
|
if (!isWordChar(key[i])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// polyfills
|
||||||
|
function isArray(obj) {
|
||||||
|
if (Array.isArray) {
|
||||||
|
return Array.isArray(obj);
|
||||||
|
} else {
|
||||||
|
return Object.prototype.toString.call(obj) === '[object Array]';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDate(obj) {
|
||||||
|
return Object.prototype.toString.call(obj) === '[object Date]';
|
||||||
|
}
|
||||||
|
|
||||||
|
var objStack = [];
|
||||||
|
function checkForCircular(obj) {
|
||||||
|
for (var i = 0; i < objStack.length; i++) {
|
||||||
|
if (objStack[i] === obj) {
|
||||||
|
throw new TypeError('Converting circular structure to JSON');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copied from Crokford's implementation of JSON
|
||||||
|
// See
|
||||||
|
// https://github.com/douglascrockford/JSON-js/blob/e39db4b7e6249f04a195e7dd0840e610cc9e941e/json2.js#L195
|
||||||
|
// Begin
|
||||||
|
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
||||||
|
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
||||||
|
meta = { // table of character substitutions
|
||||||
|
'\b': '\\b',
|
||||||
|
'\t': '\\t',
|
||||||
|
'\n': '\\n',
|
||||||
|
'\f': '\\f',
|
||||||
|
'\r': '\\r',
|
||||||
|
'"' : '\\"',
|
||||||
|
'\\': '\\\\'
|
||||||
|
};
|
||||||
|
function escapeString(str, keepQuotes) {
|
||||||
|
// If the string contains no control characters, no quote characters, and no
|
||||||
|
// backslash characters, then we can safely slap some quotes around it.
|
||||||
|
// Otherwise we must also replace the offending characters with safe escape
|
||||||
|
// sequences.
|
||||||
|
escapable.lastIndex = 0;
|
||||||
|
return escapable.test(str) && !keepQuotes ? '"' + str.replace(escapable, function(a) {
|
||||||
|
var c = meta[a];
|
||||||
|
return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||||
|
}) + '"' : '"' + str + '"';
|
||||||
|
}
|
||||||
|
// End
|
||||||
|
|
||||||
|
function internalStringify(holder, key) {
|
||||||
|
var buffer, res;
|
||||||
|
|
||||||
|
// Replace the value, if necessary
|
||||||
|
var obj_part = getReplacedValueOrUndefined(holder, key);
|
||||||
|
|
||||||
|
if (obj_part && !isDate(obj_part)) {
|
||||||
|
// unbox objects
|
||||||
|
// don't unbox dates, since will turn it into number
|
||||||
|
obj_part = obj_part.valueOf();
|
||||||
|
}
|
||||||
|
switch (typeof obj_part) {
|
||||||
|
case 'boolean':
|
||||||
|
return obj_part.toString();
|
||||||
|
|
||||||
|
case 'number':
|
||||||
|
if (isNaN(obj_part) || !isFinite(obj_part)) {
|
||||||
|
return 'null';
|
||||||
|
}
|
||||||
|
return obj_part.toString();
|
||||||
|
|
||||||
|
case 'string':
|
||||||
|
return escapeString(obj_part.toString());
|
||||||
|
|
||||||
|
case 'object':
|
||||||
|
if (obj_part === null) {
|
||||||
|
return 'null';
|
||||||
|
} else if (isArray(obj_part)) {
|
||||||
|
checkForCircular(obj_part);
|
||||||
|
buffer = '[';
|
||||||
|
objStack.push(obj_part);
|
||||||
|
|
||||||
|
for (var i = 0; i < obj_part.length; i++) {
|
||||||
|
res = internalStringify(obj_part, i);
|
||||||
|
if (res === null) {
|
||||||
|
buffer += 'null';
|
||||||
|
} /* else if (typeof res === 'undefined') { // modified to support empty array values
|
||||||
|
buffer += '';
|
||||||
|
}*/
|
||||||
|
else {
|
||||||
|
buffer += res;
|
||||||
|
}
|
||||||
|
if (i < obj_part.length - 1) {
|
||||||
|
buffer += ',';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
objStack.pop();
|
||||||
|
buffer += ']';
|
||||||
|
} else {
|
||||||
|
checkForCircular(obj_part);
|
||||||
|
buffer = '{';
|
||||||
|
var nonEmpty = false;
|
||||||
|
objStack.push(obj_part);
|
||||||
|
for (var prop in obj_part) {
|
||||||
|
if (obj_part.hasOwnProperty(prop)) {
|
||||||
|
var value = internalStringify(obj_part, prop);
|
||||||
|
if (typeof value !== 'undefined' && value !== null) {
|
||||||
|
nonEmpty = true;
|
||||||
|
key = isWord(prop) && !quoteKeys ? prop : escapeString(prop, quoteKeys);
|
||||||
|
buffer += key + ':' + value + ',';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
objStack.pop();
|
||||||
|
if (nonEmpty) {
|
||||||
|
buffer = buffer.substring(0, buffer.length - 1) + '}';
|
||||||
|
} else {
|
||||||
|
buffer = '{}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
default:
|
||||||
|
// functions and undefined should be ignored
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// special case...when undefined is used inside of
|
||||||
|
// a compound object/array, return null.
|
||||||
|
// but when top-level, return undefined
|
||||||
|
var topLevelHolder = {'': obj};
|
||||||
|
if (obj === undefined) {
|
||||||
|
return getReplacedValueOrUndefined(topLevelHolder, '');
|
||||||
|
}
|
||||||
|
return internalStringify(topLevelHolder, '');
|
||||||
|
};
|
186
yarn.lock
186
yarn.lock
|
@ -1620,11 +1620,6 @@
|
||||||
resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.35.tgz#3964c48372bf62d60616d8673dd77a9719ebac9b"
|
resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.35.tgz#3964c48372bf62d60616d8673dd77a9719ebac9b"
|
||||||
integrity sha512-2WeeXK7BuQo7yPI4WGOBum90SzF/f8rqlvpaXx4rjeTmNssGRDHWf7fgDUH90xMB3sUOu716fUK5d+OVx0+ncQ==
|
integrity sha512-2WeeXK7BuQo7yPI4WGOBum90SzF/f8rqlvpaXx4rjeTmNssGRDHWf7fgDUH90xMB3sUOu716fUK5d+OVx0+ncQ==
|
||||||
|
|
||||||
"@types/cldrjs@^0.4.22":
|
|
||||||
version "0.4.22"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/cldrjs/-/cldrjs-0.4.22.tgz#24e31cdf15a4ea806ca0a774b024150d1066fea1"
|
|
||||||
integrity sha512-YyzxXZ5s9xwPWznXnI3++X14JGnomDdDAlin7kWZvxX/MzirC9BNFcDSQ0yR8YG2M/xNMn0nXsCGkgbFVyXjGw==
|
|
||||||
|
|
||||||
"@types/cli-progress@^3.4.2":
|
"@types/cli-progress@^3.4.2":
|
||||||
version "3.9.1"
|
version "3.9.1"
|
||||||
resolved "https://registry.yarnpkg.com/@types/cli-progress/-/cli-progress-3.9.1.tgz#285e7fbdad6e7baf072d163ae1c3b23b7b219130"
|
resolved "https://registry.yarnpkg.com/@types/cli-progress/-/cli-progress-3.9.1.tgz#285e7fbdad6e7baf072d163ae1c3b23b7b219130"
|
||||||
|
@ -2137,6 +2132,11 @@ adjust-sourcemap-loader@^4.0.0:
|
||||||
loader-utils "^2.0.0"
|
loader-utils "^2.0.0"
|
||||||
regex-parser "^2.2.11"
|
regex-parser "^2.2.11"
|
||||||
|
|
||||||
|
adm-zip@0.4.11:
|
||||||
|
version "0.4.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.11.tgz#2aa54c84c4b01a9d0fb89bb11982a51f13e3d62a"
|
||||||
|
integrity sha512-L8vcjDTCOIJk7wFvmlEUN7AsSb8T+2JrdP7KINBjzr24TJ5Mwj590sLu3BC7zNZowvJWa/JtPmD8eJCzdtDWjA==
|
||||||
|
|
||||||
adm-zip@^0.4.9, adm-zip@~0.4.3:
|
adm-zip@^0.4.9, adm-zip@~0.4.3:
|
||||||
version "0.4.16"
|
version "0.4.16"
|
||||||
resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365"
|
resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365"
|
||||||
|
@ -2210,6 +2210,16 @@ ajv@8.2.0:
|
||||||
require-from-string "^2.0.2"
|
require-from-string "^2.0.2"
|
||||||
uri-js "^4.2.2"
|
uri-js "^4.2.2"
|
||||||
|
|
||||||
|
ajv@^5.1.0:
|
||||||
|
version "5.5.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965"
|
||||||
|
integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=
|
||||||
|
dependencies:
|
||||||
|
co "^4.6.0"
|
||||||
|
fast-deep-equal "^1.0.0"
|
||||||
|
fast-json-stable-stringify "^2.0.0"
|
||||||
|
json-schema-traverse "^0.3.0"
|
||||||
|
|
||||||
ajv@^6.1.0, ajv@^6.12.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5:
|
ajv@^6.1.0, ajv@^6.12.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5:
|
||||||
version "6.12.6"
|
version "6.12.6"
|
||||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
|
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
|
||||||
|
@ -2714,7 +2724,7 @@ aws-sign2@~0.7.0:
|
||||||
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
|
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
|
||||||
integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
|
integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
|
||||||
|
|
||||||
aws4@^1.8.0:
|
aws4@^1.6.0, aws4@^1.8.0:
|
||||||
version "1.11.0"
|
version "1.11.0"
|
||||||
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
|
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
|
||||||
integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
|
integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
|
||||||
|
@ -3501,20 +3511,33 @@ class-utils@^0.3.5:
|
||||||
isobject "^3.0.0"
|
isobject "^3.0.0"
|
||||||
static-extend "^0.1.1"
|
static-extend "^0.1.1"
|
||||||
|
|
||||||
cldr@5.7.0:
|
cldr-data-downloader@^0.3.5:
|
||||||
version "5.7.0"
|
version "0.3.5"
|
||||||
resolved "https://registry.yarnpkg.com/cldr/-/cldr-5.7.0.tgz#8c466bdc2500fd293462029631011adcd55bc5ae"
|
resolved "https://registry.yarnpkg.com/cldr-data-downloader/-/cldr-data-downloader-0.3.5.tgz#f5445cb9d222bf7fa8426c62e0ae9d7d4897b243"
|
||||||
integrity sha512-Pyoh0kwXJIUvbAvQoQqKIr0pKWwWfkcYCIDKWmVIxJ9HftSsg57AqyfW1EzWRcP4nJj40WX4vB/lXQ+Uw4NbNA==
|
integrity sha512-uyIMa1K98DAp/PE7dYpq2COIrkWn681Atjng1GgEzeJzYb1jANtugtp9wre6+voE+qzVC8jtWv6E/xZ1GTJdlw==
|
||||||
dependencies:
|
dependencies:
|
||||||
escodegen "^1.12.0"
|
adm-zip "0.4.11"
|
||||||
|
mkdirp "0.5.0"
|
||||||
|
nopt "3.0.x"
|
||||||
|
progress "1.1.8"
|
||||||
|
q "1.0.1"
|
||||||
|
request "~2.87.0"
|
||||||
|
request-progress "0.3.1"
|
||||||
|
|
||||||
|
cldr@7.0.0:
|
||||||
|
version "7.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/cldr/-/cldr-7.0.0.tgz#8e0f42acc21b5762842cf23a747120be898447fe"
|
||||||
|
integrity sha512-BmD93+RhHGkdVRO9LYL6kd7IA9ANxnpH1A+OM6FdhKVYXqRgBaDmt9P83VaQB6gMBaFvOl4IozW/g3ViLn9LeQ==
|
||||||
|
dependencies:
|
||||||
|
escodegen "^2.0.0"
|
||||||
esprima "^4.0.1"
|
esprima "^4.0.1"
|
||||||
memoizeasync "^1.1.0"
|
memoizeasync "^1.1.0"
|
||||||
passerror "^1.1.1"
|
passerror "^1.1.1"
|
||||||
pegjs "^0.10.0"
|
pegjs "^0.10.0"
|
||||||
seq "^0.3.5"
|
seq "^0.3.5"
|
||||||
unicoderegexp "^0.4.1"
|
unicoderegexp "^0.4.1"
|
||||||
xmldom "^0.3.0"
|
xmldom "^0.6.0"
|
||||||
xpath "^0.0.27"
|
xpath "^0.0.32"
|
||||||
|
|
||||||
cldrjs@0.5.5:
|
cldrjs@0.5.5:
|
||||||
version "0.5.5"
|
version "0.5.5"
|
||||||
|
@ -3668,6 +3691,11 @@ cloneable-readable@^1.0.0:
|
||||||
process-nextick-args "^2.0.0"
|
process-nextick-args "^2.0.0"
|
||||||
readable-stream "^2.3.5"
|
readable-stream "^2.3.5"
|
||||||
|
|
||||||
|
co@^4.6.0:
|
||||||
|
version "4.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
|
||||||
|
integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=
|
||||||
|
|
||||||
code-point-at@^1.0.0:
|
code-point-at@^1.0.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
||||||
|
@ -3768,7 +3796,7 @@ colorspace@1.1.x:
|
||||||
color "3.0.x"
|
color "3.0.x"
|
||||||
text-hex "1.0.x"
|
text-hex "1.0.x"
|
||||||
|
|
||||||
combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
|
combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.5, combined-stream@~1.0.6:
|
||||||
version "1.0.8"
|
version "1.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
|
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
|
||||||
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
|
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
|
||||||
|
@ -5235,7 +5263,7 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
|
||||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||||
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
||||||
|
|
||||||
escodegen@^1.12.0, escodegen@^1.8.1:
|
escodegen@^1.8.1:
|
||||||
version "1.14.3"
|
version "1.14.3"
|
||||||
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503"
|
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503"
|
||||||
integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==
|
integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==
|
||||||
|
@ -5502,7 +5530,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2:
|
||||||
assign-symbols "^1.0.0"
|
assign-symbols "^1.0.0"
|
||||||
is-extendable "^1.0.1"
|
is-extendable "^1.0.1"
|
||||||
|
|
||||||
extend@^3.0.0, extend@^3.0.2, extend@~3.0.2:
|
extend@^3.0.0, extend@^3.0.2, extend@~3.0.1, extend@~3.0.2:
|
||||||
version "3.0.2"
|
version "3.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
|
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
|
||||||
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
|
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
|
||||||
|
@ -5561,6 +5589,11 @@ fancy-log@^1.3.2:
|
||||||
parse-node-version "^1.0.0"
|
parse-node-version "^1.0.0"
|
||||||
time-stamp "^1.0.0"
|
time-stamp "^1.0.0"
|
||||||
|
|
||||||
|
fast-deep-equal@^1.0.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614"
|
||||||
|
integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=
|
||||||
|
|
||||||
fast-deep-equal@^3.1.1:
|
fast-deep-equal@^3.1.1:
|
||||||
version "3.1.3"
|
version "3.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
||||||
|
@ -5939,7 +5972,7 @@ form-data@^3.0.0:
|
||||||
combined-stream "^1.0.8"
|
combined-stream "^1.0.8"
|
||||||
mime-types "^2.1.12"
|
mime-types "^2.1.12"
|
||||||
|
|
||||||
form-data@~2.3.2:
|
form-data@~2.3.1, form-data@~2.3.2:
|
||||||
version "2.3.3"
|
version "2.3.3"
|
||||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
|
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
|
||||||
integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
|
integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
|
||||||
|
@ -6618,6 +6651,14 @@ har-schema@^2.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
|
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
|
||||||
integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
|
integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
|
||||||
|
|
||||||
|
har-validator@~5.0.3:
|
||||||
|
version "5.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd"
|
||||||
|
integrity sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=
|
||||||
|
dependencies:
|
||||||
|
ajv "^5.1.0"
|
||||||
|
har-schema "^2.0.0"
|
||||||
|
|
||||||
har-validator@~5.1.3:
|
har-validator@~5.1.3:
|
||||||
version "5.1.5"
|
version "5.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd"
|
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd"
|
||||||
|
@ -7861,6 +7902,11 @@ json-ptr@^2.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib "^2.2.0"
|
tslib "^2.2.0"
|
||||||
|
|
||||||
|
json-schema-traverse@^0.3.0:
|
||||||
|
version "0.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340"
|
||||||
|
integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=
|
||||||
|
|
||||||
json-schema-traverse@^0.4.1:
|
json-schema-traverse@^0.4.1:
|
||||||
version "0.4.1"
|
version "0.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
|
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
|
||||||
|
@ -8987,6 +9033,11 @@ minimist-options@4.1.0:
|
||||||
is-plain-obj "^1.1.0"
|
is-plain-obj "^1.1.0"
|
||||||
kind-of "^6.0.3"
|
kind-of "^6.0.3"
|
||||||
|
|
||||||
|
minimist@0.0.8:
|
||||||
|
version "0.0.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
|
||||||
|
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
|
||||||
|
|
||||||
minimist@1.x, minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5:
|
minimist@1.x, minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5:
|
||||||
version "1.2.5"
|
version "1.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
||||||
|
@ -9087,6 +9138,13 @@ mkdirp-classic@^0.5.2:
|
||||||
resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
|
resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
|
||||||
integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
|
integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
|
||||||
|
|
||||||
|
mkdirp@0.5.0:
|
||||||
|
version "0.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.0.tgz#1d73076a6df986cd9344e15e71fcc05a4c9abf12"
|
||||||
|
integrity sha1-HXMHam35hs2TROFecfzAWkyavxI=
|
||||||
|
dependencies:
|
||||||
|
minimist "0.0.8"
|
||||||
|
|
||||||
"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5:
|
"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5:
|
||||||
version "0.5.5"
|
version "0.5.5"
|
||||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
|
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
|
||||||
|
@ -9350,6 +9408,13 @@ nodejs-websocket@^1.7.2:
|
||||||
resolved "https://registry.yarnpkg.com/nodejs-websocket/-/nodejs-websocket-1.7.2.tgz#94abd1e248f57d4d1c663dec3831015c6dad98a6"
|
resolved "https://registry.yarnpkg.com/nodejs-websocket/-/nodejs-websocket-1.7.2.tgz#94abd1e248f57d4d1c663dec3831015c6dad98a6"
|
||||||
integrity sha512-PFX6ypJcCNDs7obRellR0DGTebfUhw1SXGKe2zpB+Ng1DQJhdzbzx1ob+AvJCLzy2TJF4r8cCDqMQqei1CZdPQ==
|
integrity sha512-PFX6ypJcCNDs7obRellR0DGTebfUhw1SXGKe2zpB+Ng1DQJhdzbzx1ob+AvJCLzy2TJF4r8cCDqMQqei1CZdPQ==
|
||||||
|
|
||||||
|
nopt@3.0.x:
|
||||||
|
version "3.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
|
||||||
|
integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k=
|
||||||
|
dependencies:
|
||||||
|
abbrev "1"
|
||||||
|
|
||||||
nopt@^5.0.0:
|
nopt@^5.0.0:
|
||||||
version "5.0.0"
|
version "5.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88"
|
resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88"
|
||||||
|
@ -9510,6 +9575,11 @@ number-is-nan@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
|
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
|
||||||
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
|
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
|
||||||
|
|
||||||
|
oauth-sign@~0.8.2:
|
||||||
|
version "0.8.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
|
||||||
|
integrity sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=
|
||||||
|
|
||||||
oauth-sign@~0.9.0:
|
oauth-sign@~0.9.0:
|
||||||
version "0.9.0"
|
version "0.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
||||||
|
@ -10895,6 +10965,11 @@ process-nextick-args@~1.0.6:
|
||||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
|
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
|
||||||
integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=
|
integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=
|
||||||
|
|
||||||
|
progress@1.1.8:
|
||||||
|
version "1.1.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be"
|
||||||
|
integrity sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=
|
||||||
|
|
||||||
progress@^2.0.1, progress@^2.0.3:
|
progress@^2.0.1, progress@^2.0.3:
|
||||||
version "2.0.3"
|
version "2.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
|
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
|
||||||
|
@ -11061,7 +11136,7 @@ punycode@1.3.2:
|
||||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
|
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
|
||||||
integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=
|
integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=
|
||||||
|
|
||||||
punycode@^1.3.2:
|
punycode@^1.3.2, punycode@^1.4.1:
|
||||||
version "1.4.1"
|
version "1.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
|
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
|
||||||
integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
|
integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
|
||||||
|
@ -11096,6 +11171,11 @@ puppeteer@5.4.1:
|
||||||
unbzip2-stream "^1.3.3"
|
unbzip2-stream "^1.3.3"
|
||||||
ws "^7.2.3"
|
ws "^7.2.3"
|
||||||
|
|
||||||
|
q@1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/q/-/q-1.0.1.tgz#11872aeedee89268110b10a718448ffb10112a14"
|
||||||
|
integrity sha1-EYcq7t7okmgRCxCnGESP+xARKhQ=
|
||||||
|
|
||||||
q@1.4.1:
|
q@1.4.1:
|
||||||
version "1.4.1"
|
version "1.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e"
|
resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e"
|
||||||
|
@ -11123,7 +11203,7 @@ qs@^6.4.0, qs@^6.6.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
side-channel "^1.0.4"
|
side-channel "^1.0.4"
|
||||||
|
|
||||||
qs@~6.5.2:
|
qs@~6.5.1, qs@~6.5.2:
|
||||||
version "6.5.2"
|
version "6.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
|
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
|
||||||
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
|
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
|
||||||
|
@ -11513,6 +11593,13 @@ replace-homedir@^1.0.0:
|
||||||
is-absolute "^1.0.0"
|
is-absolute "^1.0.0"
|
||||||
remove-trailing-separator "^1.1.0"
|
remove-trailing-separator "^1.1.0"
|
||||||
|
|
||||||
|
request-progress@0.3.1:
|
||||||
|
version "0.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-0.3.1.tgz#0721c105d8a96ac6b2ce8b2c89ae2d5ecfcf6b3a"
|
||||||
|
integrity sha1-ByHBBdipasayzossia4tXs/Pazo=
|
||||||
|
dependencies:
|
||||||
|
throttleit "~0.0.2"
|
||||||
|
|
||||||
request@^2.87.0, request@^2.88.2:
|
request@^2.87.0, request@^2.88.2:
|
||||||
version "2.88.2"
|
version "2.88.2"
|
||||||
resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
|
resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
|
||||||
|
@ -11539,6 +11626,32 @@ request@^2.87.0, request@^2.88.2:
|
||||||
tunnel-agent "^0.6.0"
|
tunnel-agent "^0.6.0"
|
||||||
uuid "^3.3.2"
|
uuid "^3.3.2"
|
||||||
|
|
||||||
|
request@~2.87.0:
|
||||||
|
version "2.87.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e"
|
||||||
|
integrity sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==
|
||||||
|
dependencies:
|
||||||
|
aws-sign2 "~0.7.0"
|
||||||
|
aws4 "^1.6.0"
|
||||||
|
caseless "~0.12.0"
|
||||||
|
combined-stream "~1.0.5"
|
||||||
|
extend "~3.0.1"
|
||||||
|
forever-agent "~0.6.1"
|
||||||
|
form-data "~2.3.1"
|
||||||
|
har-validator "~5.0.3"
|
||||||
|
http-signature "~1.2.0"
|
||||||
|
is-typedarray "~1.0.0"
|
||||||
|
isstream "~0.1.2"
|
||||||
|
json-stringify-safe "~5.0.1"
|
||||||
|
mime-types "~2.1.17"
|
||||||
|
oauth-sign "~0.8.2"
|
||||||
|
performance-now "^2.1.0"
|
||||||
|
qs "~6.5.1"
|
||||||
|
safe-buffer "^5.1.1"
|
||||||
|
tough-cookie "~2.3.3"
|
||||||
|
tunnel-agent "^0.6.0"
|
||||||
|
uuid "^3.1.0"
|
||||||
|
|
||||||
require-directory@^2.1.1:
|
require-directory@^2.1.1:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
|
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
|
||||||
|
@ -11848,7 +11961,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||||
|
|
||||||
safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@~5.2.0:
|
safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0:
|
||||||
version "5.2.1"
|
version "5.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||||
|
@ -11900,6 +12013,7 @@ sauce-connect-launcher@^1.2.4:
|
||||||
|
|
||||||
"sauce-connect@https://saucelabs.com/downloads/sc-4.6.2-linux.tar.gz":
|
"sauce-connect@https://saucelabs.com/downloads/sc-4.6.2-linux.tar.gz":
|
||||||
version "0.0.0"
|
version "0.0.0"
|
||||||
|
uid "7b7f35433af9c3380758e048894d7b9aecf3754e"
|
||||||
resolved "https://saucelabs.com/downloads/sc-4.6.2-linux.tar.gz#7b7f35433af9c3380758e048894d7b9aecf3754e"
|
resolved "https://saucelabs.com/downloads/sc-4.6.2-linux.tar.gz#7b7f35433af9c3380758e048894d7b9aecf3754e"
|
||||||
|
|
||||||
saucelabs@^1.5.0:
|
saucelabs@^1.5.0:
|
||||||
|
@ -13009,6 +13123,11 @@ text-table@0.2.0:
|
||||||
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
|
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
|
||||||
integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
|
integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
|
||||||
|
|
||||||
|
throttleit@~0.0.2:
|
||||||
|
version "0.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-0.0.2.tgz#cfedf88e60c00dd9697b61fdd2a8343a9b680eaf"
|
||||||
|
integrity sha1-z+34jmDADdlpe2H90qg0OptoDq8=
|
||||||
|
|
||||||
through2-filter@^3.0.0:
|
through2-filter@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-3.0.0.tgz#700e786df2367c2c88cd8aa5be4cf9c1e7831254"
|
resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-3.0.0.tgz#700e786df2367c2c88cd8aa5be4cf9c1e7831254"
|
||||||
|
@ -13156,6 +13275,13 @@ toidentifier@1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
|
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
|
||||||
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
|
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
|
||||||
|
|
||||||
|
tough-cookie@~2.3.3:
|
||||||
|
version "2.3.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655"
|
||||||
|
integrity sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==
|
||||||
|
dependencies:
|
||||||
|
punycode "^1.4.1"
|
||||||
|
|
||||||
tough-cookie@~2.5.0:
|
tough-cookie@~2.5.0:
|
||||||
version "2.5.0"
|
version "2.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
|
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
|
||||||
|
@ -13728,7 +13854,7 @@ uuid@8.3.2:
|
||||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
|
||||||
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
||||||
|
|
||||||
uuid@^3.0.0, uuid@^3.3.2, uuid@^3.4.0:
|
uuid@^3.0.0, uuid@^3.1.0, uuid@^3.3.2, uuid@^3.4.0:
|
||||||
version "3.4.0"
|
version "3.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
|
||||||
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
|
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
|
||||||
|
@ -14264,25 +14390,25 @@ xmlbuilder@~11.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3"
|
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3"
|
||||||
integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==
|
integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==
|
||||||
|
|
||||||
xmldom@^0.3.0:
|
|
||||||
version "0.3.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.3.0.tgz#e625457f4300b5df9c2e1ecb776147ece47f3e5a"
|
|
||||||
integrity sha512-z9s6k3wxE+aZHgXYxSTpGDo7BYOUfJsIRyoZiX6HTjwpwfS2wpQBQKa2fD+ShLyPkqDYo5ud7KitmLZ2Cd6r0g==
|
|
||||||
|
|
||||||
xmldom@^0.5.0:
|
xmldom@^0.5.0:
|
||||||
version "0.5.0"
|
version "0.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.5.0.tgz#193cb96b84aa3486127ea6272c4596354cb4962e"
|
resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.5.0.tgz#193cb96b84aa3486127ea6272c4596354cb4962e"
|
||||||
integrity sha512-Foaj5FXVzgn7xFzsKeNIde9g6aFBxTPi37iwsno8QvApmtg7KYrr+OPyRHcJF7dud2a5nGRBXK3n0dL62Gf7PA==
|
integrity sha512-Foaj5FXVzgn7xFzsKeNIde9g6aFBxTPi37iwsno8QvApmtg7KYrr+OPyRHcJF7dud2a5nGRBXK3n0dL62Gf7PA==
|
||||||
|
|
||||||
|
xmldom@^0.6.0:
|
||||||
|
version "0.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.6.0.tgz#43a96ecb8beece991cef382c08397d82d4d0c46f"
|
||||||
|
integrity sha512-iAcin401y58LckRZ0TkI4k0VSM1Qg0KGSc3i8rU+xrxe19A/BN1zHyVSJY7uoutVlaTSzYyk/v5AmkewAP7jtg==
|
||||||
|
|
||||||
xmlhttprequest-ssl@~1.5.4:
|
xmlhttprequest-ssl@~1.5.4:
|
||||||
version "1.5.5"
|
version "1.5.5"
|
||||||
resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e"
|
resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e"
|
||||||
integrity sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=
|
integrity sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=
|
||||||
|
|
||||||
xpath@^0.0.27:
|
xpath@^0.0.32:
|
||||||
version "0.0.27"
|
version "0.0.32"
|
||||||
resolved "https://registry.yarnpkg.com/xpath/-/xpath-0.0.27.tgz#dd3421fbdcc5646ac32c48531b4d7e9d0c2cfa92"
|
resolved "https://registry.yarnpkg.com/xpath/-/xpath-0.0.32.tgz#1b73d3351af736e17ec078d6da4b8175405c48af"
|
||||||
integrity sha512-fg03WRxtkCV6ohClePNAECYsmpKKTv5L8y/X3Dn1hQrec3POx2jHZ/0P2qQ6HvsrU1BmeqXcof3NGGueG6LxwQ==
|
integrity sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw==
|
||||||
|
|
||||||
xregexp@2.0.0:
|
xregexp@2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
|
|
Loading…
Reference in New Issue