@openedx/frontend-base 1.0.0-alpha.20 → 1.0.0-alpha.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/runtime/i18n/index.d.ts +1 -1
- package/dist/runtime/i18n/index.js +1 -1
- package/dist/runtime/i18n/index.js.map +1 -1
- package/dist/runtime/i18n/lib.d.ts +0 -6
- package/dist/runtime/i18n/lib.js +0 -13
- package/dist/runtime/i18n/lib.js.map +1 -1
- package/dist/shell/dev/devHome/app.js +0 -2
- package/dist/shell/dev/devHome/app.js.map +1 -1
- package/dist/shell/site.js +1 -3
- package/dist/shell/site.js.map +1 -1
- package/dist/tools/cli/commands/translations.d.ts +2 -0
- package/dist/tools/cli/commands/translations.js +20 -0
- package/dist/tools/cli/openedx.js +6 -0
- package/dist/tools/cli/utils/printUsage.js +8 -0
- package/dist/tools/cli/utils/translations/index.d.ts +2 -0
- package/dist/tools/cli/utils/translations/index.js +7 -0
- package/dist/tools/cli/utils/translations/messagesObject.d.ts +26 -0
- package/dist/tools/cli/utils/translations/messagesObject.js +66 -0
- package/dist/tools/cli/utils/translations/prepare.d.ts +5 -0
- package/dist/tools/cli/utils/translations/prepare.js +98 -0
- package/dist/tools/cli/utils/translations/pull.d.ts +6 -0
- package/dist/tools/cli/utils/translations/pull.js +102 -0
- package/dist/tools/types.d.ts +2 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/webpack/common-config/index.d.ts +1 -0
- package/dist/tools/webpack/common-config/index.js +3 -1
- package/dist/tools/webpack/common-config/site/getI18nMessagesFallbackPlugin/emptyI18n.d.ts +2 -0
- package/dist/tools/webpack/common-config/site/getI18nMessagesFallbackPlugin/emptyI18n.js +3 -0
- package/dist/tools/webpack/common-config/site/getI18nMessagesFallbackPlugin/index.d.ts +2 -0
- package/dist/tools/webpack/common-config/site/getI18nMessagesFallbackPlugin/index.js +26 -0
- package/dist/tools/webpack/utils/getResolvedSiteI18nPath.d.ts +1 -0
- package/dist/tools/webpack/utils/getResolvedSiteI18nPath.js +25 -0
- package/dist/tools/webpack/webpack.config.build.js +4 -0
- package/dist/tools/webpack/webpack.config.dev.js +4 -0
- package/dist/tools/webpack/webpack.config.dev.shell.js +3 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +14 -8
- package/dist/shell/dev/devHome/i18n/index.d.ts +0 -27
- package/dist/shell/dev/devHome/i18n/index.js +0 -28
- package/dist/shell/dev/devHome/i18n/index.js.map +0 -1
- package/dist/shell/i18n/index.d.ts +0 -25
- package/dist/shell/i18n/index.js +0 -26
- package/dist/shell/i18n/index.js.map +0 -1
- package/dist/tools/cli/intl-imports.d.ts +0 -7
- package/dist/tools/cli/intl-imports.js +0 -233
- package/dist/tools/cli/intl-imports.test.d.ts +0 -1
- package/dist/tools/cli/intl-imports.test.js +0 -146
- package/dist/tools/cli/transifex-utils.d.ts +0 -2
- package/dist/tools/cli/transifex-utils.js +0 -68
- package/dist/tools/webpack/plugins/html-webpack-new-relic-plugin/test/HtmlWebpackNewRelicPlugin.test.d.ts +0 -1
- package/dist/tools/webpack/plugins/html-webpack-new-relic-plugin/test/HtmlWebpackNewRelicPlugin.test.js +0 -66
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = getI18nMessagesFallbackPlugin;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const webpack_1 = __importDefault(require("webpack"));
|
|
10
|
+
// When messages.ts hasn't been generated yet (i.e. translations:pull hasn't been run),
|
|
11
|
+
// replace the ./messages import in src/i18n/index.ts with an empty fallback so webpack
|
|
12
|
+
// doesn't error on the missing file.
|
|
13
|
+
function getI18nMessagesFallbackPlugin() {
|
|
14
|
+
return new webpack_1.default.NormalModuleReplacementPlugin(
|
|
15
|
+
// Matches the raw import string `./messages` — anchored to avoid partial matches.
|
|
16
|
+
/^\.\/messages$/, (resource) => {
|
|
17
|
+
// Only apply to imports from src/i18n/ — exact match to avoid false positives.
|
|
18
|
+
if (resource.context !== path_1.default.resolve(process.cwd(), 'src', 'i18n'))
|
|
19
|
+
return;
|
|
20
|
+
// If messages.ts exists, let webpack resolve it normally.
|
|
21
|
+
if (fs_1.default.existsSync(path_1.default.join(resource.context, 'messages.ts')))
|
|
22
|
+
return;
|
|
23
|
+
// File is missing — substitute the empty fallback module.
|
|
24
|
+
resource.request = require.resolve('./emptyI18n');
|
|
25
|
+
});
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function getResolvedSiteI18nPath(defaultDirname: string): string;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = getResolvedSiteI18nPath;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
function getResolvedSiteI18nPath(defaultDirname) {
|
|
10
|
+
const siteI18nPath = process.env.SITE_I18N_PATH;
|
|
11
|
+
if (siteI18nPath !== undefined) {
|
|
12
|
+
const absolutePath = path_1.default.resolve(process.cwd(), siteI18nPath);
|
|
13
|
+
if (fs_1.default.existsSync(absolutePath)) {
|
|
14
|
+
return absolutePath;
|
|
15
|
+
}
|
|
16
|
+
console.error(`Invalid site i18n path (${siteI18nPath}) specified as an environment variable. Aborting.`);
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
const defaultPath = path_1.default.resolve(process.cwd(), defaultDirname);
|
|
20
|
+
if (fs_1.default.existsSync(defaultPath)) {
|
|
21
|
+
return defaultPath;
|
|
22
|
+
}
|
|
23
|
+
console.error(`Default site i18n directory (${defaultPath}) does not exist. Aborting.`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
@@ -12,7 +12,9 @@ const webpack_remove_empty_scripts_1 = __importDefault(require("webpack-remove-e
|
|
|
12
12
|
const common_config_1 = require("./common-config");
|
|
13
13
|
const getPublicPath_1 = __importDefault(require("./utils/getPublicPath"));
|
|
14
14
|
const getResolvedSiteConfigPath_1 = __importDefault(require("./utils/getResolvedSiteConfigPath"));
|
|
15
|
+
const getResolvedSiteI18nPath_1 = __importDefault(require("./utils/getResolvedSiteI18nPath"));
|
|
15
16
|
const resolvedSiteConfigPath = (0, getResolvedSiteConfigPath_1.default)('site.config.build.tsx');
|
|
17
|
+
const resolvedSiteI18nPath = (0, getResolvedSiteI18nPath_1.default)('src/i18n');
|
|
16
18
|
const config = {
|
|
17
19
|
mode: 'production',
|
|
18
20
|
devtool: 'source-map',
|
|
@@ -28,6 +30,7 @@ const config = {
|
|
|
28
30
|
resolve: {
|
|
29
31
|
alias: {
|
|
30
32
|
'site.config': resolvedSiteConfigPath,
|
|
33
|
+
'site.i18n': resolvedSiteI18nPath,
|
|
31
34
|
},
|
|
32
35
|
plugins: [
|
|
33
36
|
new tsconfig_paths_webpack_plugin_1.default({
|
|
@@ -63,6 +66,7 @@ const config = {
|
|
|
63
66
|
filename: '[name].[chunkhash].css',
|
|
64
67
|
}),
|
|
65
68
|
(0, common_config_1.getHtmlWebpackPlugin)(),
|
|
69
|
+
(0, common_config_1.getI18nMessagesFallbackPlugin)(),
|
|
66
70
|
new fork_ts_checker_webpack_plugin_1.default(),
|
|
67
71
|
new webpack_bundle_analyzer_1.BundleAnalyzerPlugin({
|
|
68
72
|
analyzerMode: 'static',
|
|
@@ -12,7 +12,9 @@ const webpack_remove_empty_scripts_1 = __importDefault(require("webpack-remove-e
|
|
|
12
12
|
const common_config_1 = require("./common-config");
|
|
13
13
|
const getPublicPath_1 = __importDefault(require("./utils/getPublicPath"));
|
|
14
14
|
const getResolvedSiteConfigPath_1 = __importDefault(require("./utils/getResolvedSiteConfigPath"));
|
|
15
|
+
const getResolvedSiteI18nPath_1 = __importDefault(require("./utils/getResolvedSiteI18nPath"));
|
|
15
16
|
const resolvedSiteConfigPath = (0, getResolvedSiteConfigPath_1.default)('site.config.dev.tsx');
|
|
17
|
+
const resolvedSiteI18nPath = (0, getResolvedSiteI18nPath_1.default)('src/i18n');
|
|
16
18
|
const config = {
|
|
17
19
|
entry: {
|
|
18
20
|
app: '@openedx/frontend-base/shell/site',
|
|
@@ -24,6 +26,7 @@ const config = {
|
|
|
24
26
|
resolve: {
|
|
25
27
|
alias: {
|
|
26
28
|
'site.config': resolvedSiteConfigPath,
|
|
29
|
+
'site.i18n': resolvedSiteI18nPath,
|
|
27
30
|
},
|
|
28
31
|
plugins: [
|
|
29
32
|
new tsconfig_paths_webpack_plugin_1.default({
|
|
@@ -59,6 +62,7 @@ const config = {
|
|
|
59
62
|
filename: '[name].css',
|
|
60
63
|
}),
|
|
61
64
|
(0, common_config_1.getHtmlWebpackPlugin)(),
|
|
65
|
+
(0, common_config_1.getI18nMessagesFallbackPlugin)(),
|
|
62
66
|
new react_refresh_webpack_plugin_1.default(),
|
|
63
67
|
new fork_ts_checker_webpack_plugin_1.default(),
|
|
64
68
|
],
|
|
@@ -14,7 +14,9 @@ const common_config_1 = require("./common-config");
|
|
|
14
14
|
const html_webpack_plugin_1 = __importDefault(require("html-webpack-plugin"));
|
|
15
15
|
const getPublicPath_1 = __importDefault(require("./utils/getPublicPath"));
|
|
16
16
|
const getResolvedSiteConfigPath_1 = __importDefault(require("./utils/getResolvedSiteConfigPath"));
|
|
17
|
+
const getResolvedSiteI18nPath_1 = __importDefault(require("./utils/getResolvedSiteI18nPath"));
|
|
17
18
|
const resolvedSiteConfigPath = (0, getResolvedSiteConfigPath_1.default)('shell/site.config.dev.tsx');
|
|
19
|
+
const resolvedSiteI18nPath = (0, getResolvedSiteI18nPath_1.default)('test-site/src/i18n');
|
|
18
20
|
const config = {
|
|
19
21
|
entry: {
|
|
20
22
|
app: path_1.default.resolve(process.cwd(), 'shell/site'),
|
|
@@ -26,6 +28,7 @@ const config = {
|
|
|
26
28
|
resolve: {
|
|
27
29
|
alias: {
|
|
28
30
|
'site.config': resolvedSiteConfigPath,
|
|
31
|
+
'site.i18n': resolvedSiteI18nPath,
|
|
29
32
|
},
|
|
30
33
|
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
|
31
34
|
},
|
package/dist/types.d.ts
CHANGED
|
@@ -20,7 +20,6 @@ export type AppProvider = FC<{
|
|
|
20
20
|
}>;
|
|
21
21
|
export interface App {
|
|
22
22
|
appId: string;
|
|
23
|
-
messages?: LocalizedMessages;
|
|
24
23
|
routes?: RoleRouteObject[];
|
|
25
24
|
providers?: AppProvider[];
|
|
26
25
|
slots?: SlotOperation[];
|
|
@@ -35,6 +34,7 @@ export interface RequiredSiteConfig {
|
|
|
35
34
|
logoutUrl: string;
|
|
36
35
|
}
|
|
37
36
|
export type LocalizedMessages = Record<string, Record<string, string>>;
|
|
37
|
+
export type SiteMessages = LocalizedMessages[];
|
|
38
38
|
export interface OptionalSiteConfig {
|
|
39
39
|
environment: EnvironmentTypes;
|
|
40
40
|
apps: App[];
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"AAgHA,MAAM,CAAN,IAAY,gBAIX;AAJD,WAAY,gBAAgB;IAC1B,6CAAyB,CAAA;IACzB,+CAA2B,CAAA;IAC3B,iCAAa,CAAA;AACf,CAAC,EAJW,gBAAgB,KAAhB,gBAAgB,QAI3B","sourcesContent":["import { FC, ReactElement, ReactNode } from 'react';\nimport { MessageDescriptor } from 'react-intl';\nimport { RouteObject } from 'react-router';\nimport { SlotOperation } from './runtime/slots/types';\n\n// Apps\n\nexport interface ExternalRoute {\n role: string,\n url: string,\n}\n\nexport type RoleRouteObject = RouteObject & {\n handle?: {\n /**\n * A route role is used to identify a route that fulfills a particular role in the site.\n */\n role?: string,\n },\n};\n\nexport type AppConfig = Record<string, unknown>;\n\nexport type AppProvider = FC<{ children?: ReactNode }>;\n\nexport interface App {\n appId: string,\n
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"AAgHA,MAAM,CAAN,IAAY,gBAIX;AAJD,WAAY,gBAAgB;IAC1B,6CAAyB,CAAA;IACzB,+CAA2B,CAAA;IAC3B,iCAAa,CAAA;AACf,CAAC,EAJW,gBAAgB,KAAhB,gBAAgB,QAI3B","sourcesContent":["import { FC, ReactElement, ReactNode } from 'react';\nimport { MessageDescriptor } from 'react-intl';\nimport { RouteObject } from 'react-router';\nimport { SlotOperation } from './runtime/slots/types';\n\n// Apps\n\nexport interface ExternalRoute {\n role: string,\n url: string,\n}\n\nexport type RoleRouteObject = RouteObject & {\n handle?: {\n /**\n * A route role is used to identify a route that fulfills a particular role in the site.\n */\n role?: string,\n },\n};\n\nexport type AppConfig = Record<string, unknown>;\n\nexport type AppProvider = FC<{ children?: ReactNode }>;\n\nexport interface App {\n appId: string,\n routes?: RoleRouteObject[],\n providers?: AppProvider[],\n slots?: SlotOperation[],\n config?: AppConfig,\n}\n\n// Site Config\n\nexport interface RequiredSiteConfig {\n siteId: string,\n siteName: string,\n baseUrl: string,\n\n // Backends\n lmsBaseUrl: string,\n\n // Frontends\n loginUrl: string,\n logoutUrl: string,\n}\n\nexport type LocalizedMessages = Record<string, Record<string, string>>;\nexport type SiteMessages = LocalizedMessages[];\n\nexport interface OptionalSiteConfig {\n // Site environment\n environment: EnvironmentTypes,\n\n // Apps, routes, and URLs\n apps: App[],\n basename: string,\n externalRoutes: ExternalRoute[],\n externalLinkUrlOverrides: string[],\n runtimeConfigJsonUrl: string | null,\n commonAppConfig: AppConfig,\n headerLogoImageUrl: string,\n\n // Theme\n theme: Theme,\n\n // Cookies\n accessTokenCookieName: string,\n languagePreferenceCookieName: string,\n userInfoCookieName: string,\n\n // Paths\n csrfTokenApiPath: string,\n refreshAccessTokenApiPath: string,\n\n // Logging\n ignoredErrorRegex: RegExp | null,\n\n // Analytics\n segmentKey: string | null,\n}\n\nexport type SiteConfig = RequiredSiteConfig & Partial<OptionalSiteConfig>;\n\nexport interface ThemeVariant {\n url: string,\n}\n\nexport interface ThemeDefaults {\n light?: string,\n dark?: string,\n}\n\nexport type ThemeVariants = Record<string, ThemeVariant>;\n\nexport interface Theme {\n core?: ThemeVariant,\n defaults?: ThemeDefaults,\n variants?: ThemeVariants,\n}\n\nexport interface User {\n administrator: boolean,\n email: string,\n name: string,\n roles: string[],\n userId: number,\n username: string,\n avatar: string,\n}\n\nexport enum EnvironmentTypes {\n PRODUCTION = 'production',\n DEVELOPMENT = 'development',\n TEST = 'test',\n}\n\n// Menu Items\n\nexport type MenuItemName = string | MessageDescriptor | ReactElement;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openedx/frontend-base",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.22",
|
|
4
4
|
"description": "Build tools, setup and config for frontend apps",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -16,9 +16,13 @@
|
|
|
16
16
|
"/dist"
|
|
17
17
|
],
|
|
18
18
|
"bin": {
|
|
19
|
-
"
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
"openedx": "./dist/tools/cli/openedx.js"
|
|
20
|
+
},
|
|
21
|
+
"atlasTranslations": {
|
|
22
|
+
"path": "translations/frontend-base/src/i18n/messages",
|
|
23
|
+
"dependencies": [
|
|
24
|
+
"@openedx/paragon"
|
|
25
|
+
]
|
|
22
26
|
},
|
|
23
27
|
"scripts": {
|
|
24
28
|
"build": "make build",
|
|
@@ -26,7 +30,9 @@
|
|
|
26
30
|
"dev": "npm run build && node ./dist/tools/cli/openedx.js dev:shell",
|
|
27
31
|
"docs": "jsdoc -c jsdoc.json",
|
|
28
32
|
"lint": "eslint .; npm run lint:tools; npm --prefix ./test-site run lint",
|
|
33
|
+
"lint:fix": "eslint . --fix; npm run lint:fix:tools",
|
|
29
34
|
"lint:tools": "cd ./tools && eslint . && cd ..",
|
|
35
|
+
"lint:fix:tools": "cd ./tools && eslint . --fix && cd ..",
|
|
30
36
|
"pack": "mkdir -p pack && npm pack --silent --pack-destination pack >/dev/null && mv \"$(ls -t pack/*.tgz | head -n 1)\" pack/openedx-frontend-base.tgz",
|
|
31
37
|
"prepack": "npm run build",
|
|
32
38
|
"test": "jest",
|
|
@@ -123,7 +129,7 @@
|
|
|
123
129
|
"sharp": "^0.33.5",
|
|
124
130
|
"source-map-loader": "4.0.2",
|
|
125
131
|
"style-loader": "^4.0.0",
|
|
126
|
-
"ts-loader": "^9.5.
|
|
132
|
+
"ts-loader": "^9.5.7",
|
|
127
133
|
"tsconfig-paths-webpack-plugin": "^4.2.0",
|
|
128
134
|
"typescript": "^5.6.3",
|
|
129
135
|
"typescript-eslint": "^8.11.0",
|
|
@@ -143,12 +149,12 @@
|
|
|
143
149
|
"@testing-library/jest-dom": "^6.6.3",
|
|
144
150
|
"@testing-library/react": "^16.3.0",
|
|
145
151
|
"@testing-library/user-event": "^14.6.1",
|
|
146
|
-
"@tsconfig/
|
|
152
|
+
"@tsconfig/node24": "^24.0.4",
|
|
147
153
|
"@types/compression": "^1.7.5",
|
|
148
154
|
"@types/jest": "^29.5.14",
|
|
149
155
|
"@types/lodash.camelcase": "^4.3.9",
|
|
150
156
|
"@types/lodash.merge": "^4.6.9",
|
|
151
|
-
"@types/node": "^
|
|
157
|
+
"@types/node": "^24.12.0",
|
|
152
158
|
"@types/react": "^18.3.20",
|
|
153
159
|
"@types/react-dom": "^18.3.6",
|
|
154
160
|
"axios-mock-adapter": "^1.22.0",
|
|
@@ -157,7 +163,7 @@
|
|
|
157
163
|
"nodemon": "^3.1.4"
|
|
158
164
|
},
|
|
159
165
|
"peerDependencies": {
|
|
160
|
-
"@openedx/paragon": "^23.
|
|
166
|
+
"@openedx/paragon": "^23.20.0",
|
|
161
167
|
"@tanstack/react-query": "^5.81.2",
|
|
162
168
|
"react": "^18.3.1",
|
|
163
169
|
"react-dom": "^18.3.1",
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
declare const _default: {
|
|
2
|
-
ar: {};
|
|
3
|
-
'zh-hk': {};
|
|
4
|
-
'zh-cn': {};
|
|
5
|
-
uk: {};
|
|
6
|
-
'tr-tr': {};
|
|
7
|
-
th: {};
|
|
8
|
-
te: {};
|
|
9
|
-
ru: {};
|
|
10
|
-
'pt-pt': {};
|
|
11
|
-
'pt-br': {};
|
|
12
|
-
'it-it': {};
|
|
13
|
-
id: {};
|
|
14
|
-
hi: {};
|
|
15
|
-
he: {};
|
|
16
|
-
'fr-ca': {
|
|
17
|
-
'home.content': string;
|
|
18
|
-
};
|
|
19
|
-
fa: {};
|
|
20
|
-
'es-es': {};
|
|
21
|
-
'es-419': {};
|
|
22
|
-
el: {};
|
|
23
|
-
'de-de': {};
|
|
24
|
-
da: {};
|
|
25
|
-
bo: {};
|
|
26
|
-
};
|
|
27
|
-
export default _default;
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
// Placeholder be overridden by `make pull_translations`
|
|
2
|
-
export default {
|
|
3
|
-
ar: {},
|
|
4
|
-
'zh-hk': {},
|
|
5
|
-
'zh-cn': {},
|
|
6
|
-
uk: {},
|
|
7
|
-
'tr-tr': {},
|
|
8
|
-
th: {},
|
|
9
|
-
te: {},
|
|
10
|
-
ru: {},
|
|
11
|
-
'pt-pt': {},
|
|
12
|
-
'pt-br': {},
|
|
13
|
-
'it-it': {},
|
|
14
|
-
id: {},
|
|
15
|
-
hi: {},
|
|
16
|
-
he: {},
|
|
17
|
-
'fr-ca': {
|
|
18
|
-
'home.content': 'Home content in French.'
|
|
19
|
-
},
|
|
20
|
-
fa: {},
|
|
21
|
-
'es-es': {},
|
|
22
|
-
'es-419': {},
|
|
23
|
-
el: {},
|
|
24
|
-
'de-de': {},
|
|
25
|
-
da: {},
|
|
26
|
-
bo: {},
|
|
27
|
-
};
|
|
28
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../shell/dev/devHome/i18n/index.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,eAAe;IACb,EAAE,EAAE,EAAE;IACN,OAAO,EAAE,EAAE;IACX,OAAO,EAAE,EAAE;IACX,EAAE,EAAE,EAAE;IACN,OAAO,EAAE,EAAE;IACX,EAAE,EAAE,EAAE;IACN,EAAE,EAAE,EAAE;IACN,EAAE,EAAE,EAAE;IACN,OAAO,EAAE,EAAE;IACX,OAAO,EAAE,EAAE;IACX,OAAO,EAAE,EAAE;IACX,EAAE,EAAE,EAAE;IACN,EAAE,EAAE,EAAE;IACN,EAAE,EAAE,EAAE;IACN,OAAO,EAAE;QACP,cAAc,EAAE,yBAAyB;KAC1C;IACD,EAAE,EAAE,EAAE;IACN,OAAO,EAAE,EAAE;IACX,QAAQ,EAAE,EAAE;IACZ,EAAE,EAAE,EAAE;IACN,OAAO,EAAE,EAAE;IACX,EAAE,EAAE,EAAE;IACN,EAAE,EAAE,EAAE;CACP,CAAC","sourcesContent":["// Placeholder be overridden by `make pull_translations`\nexport default {\n ar: {},\n 'zh-hk': {},\n 'zh-cn': {},\n uk: {},\n 'tr-tr': {},\n th: {},\n te: {},\n ru: {},\n 'pt-pt': {},\n 'pt-br': {},\n 'it-it': {},\n id: {},\n hi: {},\n he: {},\n 'fr-ca': {\n 'home.content': 'Home content in French.'\n },\n fa: {},\n 'es-es': {},\n 'es-419': {},\n el: {},\n 'de-de': {},\n da: {},\n bo: {},\n};\n"]}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
declare const _default: {
|
|
2
|
-
ar: {};
|
|
3
|
-
'zh-hk': {};
|
|
4
|
-
'zh-cn': {};
|
|
5
|
-
uk: {};
|
|
6
|
-
'tr-tr': {};
|
|
7
|
-
th: {};
|
|
8
|
-
te: {};
|
|
9
|
-
ru: {};
|
|
10
|
-
'pt-pt': {};
|
|
11
|
-
'pt-br': {};
|
|
12
|
-
'it-it': {};
|
|
13
|
-
id: {};
|
|
14
|
-
hi: {};
|
|
15
|
-
he: {};
|
|
16
|
-
'fr-ca': {};
|
|
17
|
-
fa: {};
|
|
18
|
-
'es-es': {};
|
|
19
|
-
'es-419': {};
|
|
20
|
-
el: {};
|
|
21
|
-
'de-de': {};
|
|
22
|
-
da: {};
|
|
23
|
-
bo: {};
|
|
24
|
-
};
|
|
25
|
-
export default _default;
|
package/dist/shell/i18n/index.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
// Placeholder be overridden by `make pull_translations`
|
|
2
|
-
export default {
|
|
3
|
-
ar: {},
|
|
4
|
-
'zh-hk': {},
|
|
5
|
-
'zh-cn': {},
|
|
6
|
-
uk: {},
|
|
7
|
-
'tr-tr': {},
|
|
8
|
-
th: {},
|
|
9
|
-
te: {},
|
|
10
|
-
ru: {},
|
|
11
|
-
'pt-pt': {},
|
|
12
|
-
'pt-br': {},
|
|
13
|
-
'it-it': {},
|
|
14
|
-
id: {},
|
|
15
|
-
hi: {},
|
|
16
|
-
he: {},
|
|
17
|
-
'fr-ca': {},
|
|
18
|
-
fa: {},
|
|
19
|
-
'es-es': {},
|
|
20
|
-
'es-419': {},
|
|
21
|
-
el: {},
|
|
22
|
-
'de-de': {},
|
|
23
|
-
da: {},
|
|
24
|
-
bo: {},
|
|
25
|
-
};
|
|
26
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../shell/i18n/index.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,eAAe;IACb,EAAE,EAAE,EAAE;IACN,OAAO,EAAE,EAAE;IACX,OAAO,EAAE,EAAE;IACX,EAAE,EAAE,EAAE;IACN,OAAO,EAAE,EAAE;IACX,EAAE,EAAE,EAAE;IACN,EAAE,EAAE,EAAE;IACN,EAAE,EAAE,EAAE;IACN,OAAO,EAAE,EAAE;IACX,OAAO,EAAE,EAAE;IACX,OAAO,EAAE,EAAE;IACX,EAAE,EAAE,EAAE;IACN,EAAE,EAAE,EAAE;IACN,EAAE,EAAE,EAAE;IACN,OAAO,EAAE,EAAE;IACX,EAAE,EAAE,EAAE;IACN,OAAO,EAAE,EAAE;IACX,QAAQ,EAAE,EAAE;IACZ,EAAE,EAAE,EAAE;IACN,OAAO,EAAE,EAAE;IACX,EAAE,EAAE,EAAE;IACN,EAAE,EAAE,EAAE;CACP,CAAC","sourcesContent":["// Placeholder be overridden by `make pull_translations`\nexport default {\n ar: {},\n 'zh-hk': {},\n 'zh-cn': {},\n uk: {},\n 'tr-tr': {},\n th: {},\n te: {},\n ru: {},\n 'pt-pt': {},\n 'pt-br': {},\n 'it-it': {},\n id: {},\n hi: {},\n he: {},\n 'fr-ca': {},\n fa: {},\n 'es-es': {},\n 'es-419': {},\n el: {},\n 'de-de': {},\n da: {},\n bo: {},\n};\n"]}
|
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
-
};
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.main = main;
|
|
8
|
-
const scriptHelpDocument = `
|
|
9
|
-
NAME
|
|
10
|
-
intl-imports.js — Script to generate the src/i18n/index.js file that exports messages from all the languages for Micro-frontends.
|
|
11
|
-
|
|
12
|
-
SYNOPSIS
|
|
13
|
-
intl-imports.js [DIRECTORY ...]
|
|
14
|
-
|
|
15
|
-
DESCRIPTION
|
|
16
|
-
This script is intended to run after 'atlas' has pulled the files.
|
|
17
|
-
|
|
18
|
-
This expects to run inside a Micro-frontend root directory with the following structure:
|
|
19
|
-
|
|
20
|
-
frontend-app-learning $ tree src/i18n/
|
|
21
|
-
src/i18n/
|
|
22
|
-
├── index.js
|
|
23
|
-
└── messages
|
|
24
|
-
├── frontend-app-example
|
|
25
|
-
│ ├── ar.json
|
|
26
|
-
│ ├── es_419.json
|
|
27
|
-
│ └── zh_CN.json
|
|
28
|
-
├── frontend-component-footer
|
|
29
|
-
│ ├── ar.json
|
|
30
|
-
│ ├── es_419.json
|
|
31
|
-
│ └── zh_CN.json
|
|
32
|
-
└── frontend-component-header (empty directory)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
With the structure above it's expected to run with the following command in Makefile:
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
$ node_modules/.bin/intl-imports.js frontend-component-footer frontend-component-header frontend-app-example
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
It will generate two type of files:
|
|
43
|
-
|
|
44
|
-
- Main src/i18n/index.js which overrides the Micro-frontend provided with a sample output of:
|
|
45
|
-
|
|
46
|
-
"""
|
|
47
|
-
import messagesFromFrontendComponentFooter from './messages/frontend-component-footer';
|
|
48
|
-
// Skipped import due to missing './messages/frontend-component-footer/index.js' likely due to empty translations.
|
|
49
|
-
import messagesFromFrontendAppExample from './messages/frontend-app-example';
|
|
50
|
-
|
|
51
|
-
export default [
|
|
52
|
-
messagesFromFrontendComponentFooter,
|
|
53
|
-
messagesFromFrontendAppExample,
|
|
54
|
-
];
|
|
55
|
-
"""
|
|
56
|
-
|
|
57
|
-
- Each sub-directory has src/i18n/messages/frontend-component-header/index.js which is imported by the main file.:
|
|
58
|
-
|
|
59
|
-
"""
|
|
60
|
-
import messagesOfArLanguage from './ar.json';
|
|
61
|
-
import messagesOfDeLanguage from './de.json';
|
|
62
|
-
import messagesOfEs419Language from './es_419.json';
|
|
63
|
-
export default {
|
|
64
|
-
'ar': messagesOfArLanguage,
|
|
65
|
-
'de': messagesOfDeLanguage,
|
|
66
|
-
'es-419': messagesOfEs419Language,
|
|
67
|
-
};
|
|
68
|
-
"""
|
|
69
|
-
`;
|
|
70
|
-
const fs_1 = __importDefault(require("fs"));
|
|
71
|
-
const lodash_camelcase_1 = __importDefault(require("lodash.camelcase"));
|
|
72
|
-
const path_1 = __importDefault(require("path"));
|
|
73
|
-
const loggingPrefix = path_1.default.basename(`${__filename}`); // the name of this JS file
|
|
74
|
-
// Header note for generated src/i18n/index.js file
|
|
75
|
-
const filesCodeGeneratorNoticeHeader = `// This file is generated by the openedx/frontend-base's "intl-import.js" script.
|
|
76
|
-
//
|
|
77
|
-
// Refer to the i18n documents in https://docs.openedx.org/en/latest/developers/references/i18n.html to update
|
|
78
|
-
// the file and use the Micro-frontend i18n pattern in new repositories.
|
|
79
|
-
//
|
|
80
|
-
`;
|
|
81
|
-
/**
|
|
82
|
-
* Create frontend-app-example/index.js file with proper imports.
|
|
83
|
-
*
|
|
84
|
-
* @param directory - a directory name containing .json files from Transifex e.g. "frontend-app-example".
|
|
85
|
-
* @param log - Mockable process.stdout.write
|
|
86
|
-
* @param writeFileSync - Mockable fs.writeFileSync
|
|
87
|
-
* @param i18nDir - Path to `src/i18n` directory
|
|
88
|
-
*
|
|
89
|
-
* @return object - An object containing directory name and whether its "index.js" file was successfully written.
|
|
90
|
-
*/
|
|
91
|
-
function generateSubdirectoryMessageFile({ directory, log, writeFileSync, i18nDir, }) {
|
|
92
|
-
const importLines = [];
|
|
93
|
-
const messagesLines = [];
|
|
94
|
-
const counter = { nonEmptyLanguages: 0 };
|
|
95
|
-
const messagesDir = `${i18nDir}/messages`; // The directory of Micro-frontend i18n messages
|
|
96
|
-
try {
|
|
97
|
-
const files = fs_1.default.readdirSync(`${messagesDir}/${directory}`, { withFileTypes: true });
|
|
98
|
-
files.sort(); // Sorting ensures a consistent generated `index.js` order of imports cross-platforms.
|
|
99
|
-
const jsonFiles = files.filter(file => file.isFile() && file.name.endsWith('.json'));
|
|
100
|
-
if (!jsonFiles.length) {
|
|
101
|
-
log(`${loggingPrefix}: Not creating '${directory}/index.js' because no .json translation files were found.\n`);
|
|
102
|
-
return {
|
|
103
|
-
directory,
|
|
104
|
-
isWritten: false,
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
jsonFiles.forEach((file) => {
|
|
108
|
-
const filename = file.name;
|
|
109
|
-
// Gets `fr_CA` from `fr_CA.json`
|
|
110
|
-
const languageCode = filename.replace(/\.json$/, '');
|
|
111
|
-
// React-friendly language code fr_CA --> fr-ca
|
|
112
|
-
const reactIntlLanguageCode = languageCode.toLowerCase().replace(/_/g, '-');
|
|
113
|
-
// camelCase variable name
|
|
114
|
-
const messagesCamelCaseVar = (0, lodash_camelcase_1.default)(`messages_Of_${languageCode}_Language`);
|
|
115
|
-
const filePath = `${messagesDir}/${directory}/${filename}`;
|
|
116
|
-
try {
|
|
117
|
-
const entries = JSON.parse(fs_1.default.readFileSync(filePath, { encoding: 'utf8' }));
|
|
118
|
-
if (!Object.keys(entries).length) {
|
|
119
|
-
importLines.push(`// Note: Skipped empty '${filename}' messages file.`);
|
|
120
|
-
return; // Skip the language
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
catch (e) {
|
|
124
|
-
importLines.push(`// Error: unable to parse '${filename}' messages file.`);
|
|
125
|
-
log(`${loggingPrefix}: NOTICE: Skipping '${directory}/${filename}' due to error: ${e}.\n`);
|
|
126
|
-
return; // Skip the language
|
|
127
|
-
}
|
|
128
|
-
counter.nonEmptyLanguages += 1;
|
|
129
|
-
importLines.push(`import ${messagesCamelCaseVar} from './${filename}';`);
|
|
130
|
-
messagesLines.splice(1, 0, ` '${reactIntlLanguageCode}': ${messagesCamelCaseVar},`);
|
|
131
|
-
});
|
|
132
|
-
if (counter.nonEmptyLanguages) {
|
|
133
|
-
// See the help message above for sample output.
|
|
134
|
-
const messagesFileContent = [
|
|
135
|
-
filesCodeGeneratorNoticeHeader,
|
|
136
|
-
importLines.join('\n'),
|
|
137
|
-
'\nexport default {',
|
|
138
|
-
messagesLines.join('\n'),
|
|
139
|
-
'};\n',
|
|
140
|
-
].join('\n');
|
|
141
|
-
writeFileSync(`${messagesDir}/${directory}/index.js`, messagesFileContent);
|
|
142
|
-
return {
|
|
143
|
-
directory,
|
|
144
|
-
isWritten: true,
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
log(`${loggingPrefix}: Skipping '${directory}' because no languages were found.\n`);
|
|
148
|
-
}
|
|
149
|
-
catch (e) {
|
|
150
|
-
log(`${loggingPrefix}: NOTICE: Skipping '${directory}' due to error: ${e}.\n`);
|
|
151
|
-
}
|
|
152
|
-
return {
|
|
153
|
-
directory,
|
|
154
|
-
isWritten: false,
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Create main `src/i18n/index.js` messages import file.
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
* @param processedDirectories - List of directories with a boolean flag whether its "index.js" file is written
|
|
162
|
-
* The format is "[\{ directory: "frontend-component-example", isWritten: false \}, ...]"
|
|
163
|
-
* @param log - Mockable process.stdout.write
|
|
164
|
-
* @param writeFileSync - Mockable fs.writeFileSync
|
|
165
|
-
* @param i18nDir` - Path to `src/i18n` directory
|
|
166
|
-
*/
|
|
167
|
-
function generateMainMessagesFile({ processedDirectories, log, writeFileSync, i18nDir, }) {
|
|
168
|
-
const importLines = [];
|
|
169
|
-
const exportLines = [];
|
|
170
|
-
processedDirectories.forEach(processedDirectory => {
|
|
171
|
-
const { directory, isWritten } = processedDirectory;
|
|
172
|
-
if (isWritten) {
|
|
173
|
-
const moduleCamelCaseVariableName = (0, lodash_camelcase_1.default)(`messages_from_${directory}`);
|
|
174
|
-
importLines.push(`import ${moduleCamelCaseVariableName} from './messages/${directory}';`);
|
|
175
|
-
exportLines.push(` ${moduleCamelCaseVariableName},`);
|
|
176
|
-
}
|
|
177
|
-
else {
|
|
178
|
-
const skipMessage = `Skipped import due to missing '${directory}/index.js' likely due to empty translations.`;
|
|
179
|
-
importLines.push(`// ${skipMessage}.`);
|
|
180
|
-
log(`${loggingPrefix}: ${skipMessage}\n`);
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
// See the help message above for sample output.
|
|
184
|
-
const indexFileContent = [
|
|
185
|
-
filesCodeGeneratorNoticeHeader,
|
|
186
|
-
importLines.join('\n'),
|
|
187
|
-
'\nexport default [',
|
|
188
|
-
exportLines.join('\n'),
|
|
189
|
-
'];\n',
|
|
190
|
-
].join('\n');
|
|
191
|
-
writeFileSync(`${i18nDir}/index.js`, indexFileContent);
|
|
192
|
-
}
|
|
193
|
-
/*
|
|
194
|
-
* Main function of the file.
|
|
195
|
-
*/
|
|
196
|
-
function main({ directories, log, writeFileSync, pwd, }) {
|
|
197
|
-
const i18nDir = `${pwd}/src/i18n`; // The Micro-frontend i18n root directory
|
|
198
|
-
if (directories.includes('--help') || directories.includes('-h')) {
|
|
199
|
-
log(scriptHelpDocument);
|
|
200
|
-
}
|
|
201
|
-
else if (!directories.length) {
|
|
202
|
-
log(scriptHelpDocument);
|
|
203
|
-
log(`${loggingPrefix}: Error: A list of directories is required.\n`);
|
|
204
|
-
}
|
|
205
|
-
else if (!fs_1.default.existsSync(i18nDir) || !fs_1.default.lstatSync(i18nDir).isDirectory()) {
|
|
206
|
-
log(scriptHelpDocument);
|
|
207
|
-
log(`${loggingPrefix}: Error: src/i18n directory was not found.\n`);
|
|
208
|
-
}
|
|
209
|
-
else {
|
|
210
|
-
// If we're here, we know that directories is an array, so cast it as one.
|
|
211
|
-
const processedDirectories = directories.map((directory) => generateSubdirectoryMessageFile({
|
|
212
|
-
directory,
|
|
213
|
-
log,
|
|
214
|
-
writeFileSync,
|
|
215
|
-
i18nDir,
|
|
216
|
-
}));
|
|
217
|
-
generateMainMessagesFile({
|
|
218
|
-
processedDirectories,
|
|
219
|
-
log,
|
|
220
|
-
writeFileSync,
|
|
221
|
-
i18nDir,
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
if (require.main === module) {
|
|
226
|
-
// Run the main() function if called from the command line.
|
|
227
|
-
main({
|
|
228
|
-
directories: process.argv.slice(2),
|
|
229
|
-
log: text => process.stdout.write(text),
|
|
230
|
-
writeFileSync: fs_1.default.writeFileSync,
|
|
231
|
-
pwd: process.env.PWD ?? '.',
|
|
232
|
-
});
|
|
233
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|