@forge/manifest 7.7.0-next.12 → 7.7.0-next.13
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/CHANGELOG.md +11 -0
- package/out/schema/manifest-schema.json +2 -1
- package/out/utils/i18n/index.d.ts +0 -1
- package/out/utils/i18n/index.d.ts.map +1 -1
- package/out/utils/i18n/index.js +0 -1
- package/out/utils/i18n/module-i18n-helper.d.ts +0 -7
- package/out/utils/i18n/module-i18n-helper.d.ts.map +1 -1
- package/out/utils/i18n/module-i18n-helper.js +4 -56
- package/out/utils/i18n/type-check.d.ts +7 -0
- package/out/utils/i18n/type-check.d.ts.map +1 -0
- package/out/utils/i18n/type-check.js +4 -0
- package/out/validators/translations-validator.d.ts.map +1 -1
- package/out/validators/translations-validator.js +20 -26
- package/package.json +2 -1
- package/out/utils/i18n/translation-value-getter.d.ts +0 -11
- package/out/utils/i18n/translation-value-getter.d.ts.map +0 -1
- package/out/utils/i18n/translation-value-getter.js +0 -24
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @forge/manifest
|
|
2
2
|
|
|
3
|
+
## 7.7.0-next.13
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 23f6675: Make `@forge/manifest` depends on `@forge/i18n` to access i18n related helper functions.
|
|
8
|
+
- 27249cd: Make i18n fallback syntax confirm to industry convention. That is, `en-US: en-GB` indicate `en-GB` is fallback to `en-US`
|
|
9
|
+
- 5f82d22: Update manifest definitions
|
|
10
|
+
- Updated dependencies [23f6675]
|
|
11
|
+
- Updated dependencies [27249cd]
|
|
12
|
+
- @forge/i18n@0.0.1-next.12
|
|
13
|
+
|
|
3
14
|
## 7.7.0-next.12
|
|
4
15
|
|
|
5
16
|
### Patch Changes
|
|
@@ -23257,7 +23257,8 @@
|
|
|
23257
23257
|
},
|
|
23258
23258
|
"name": {
|
|
23259
23259
|
"type": "string",
|
|
23260
|
-
"minLength": 1
|
|
23260
|
+
"minLength": 1,
|
|
23261
|
+
"maxLength": 30
|
|
23261
23262
|
},
|
|
23262
23263
|
"description": {
|
|
23263
23264
|
"minLength": 1,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/i18n/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/i18n/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC"}
|
package/out/utils/i18n/index.js
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
1
|
import { Modules } from '../../schema/manifest';
|
|
2
|
-
export declare type ModuleI18nProperties = {
|
|
3
|
-
propertyPath: string[];
|
|
4
|
-
moduleName: string;
|
|
5
|
-
key: string;
|
|
6
|
-
}[];
|
|
7
|
-
export declare const extractI18nPropertiesFromModules: (modules: Modules) => ModuleI18nProperties;
|
|
8
|
-
export declare const extractI18nKeysFromModules: (modules: Modules) => string[];
|
|
9
2
|
export declare const extractInternalI18nPropertyKeysFromModules: (modules: Modules) => [string, string][];
|
|
10
3
|
//# sourceMappingURL=module-i18n-helper.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-i18n-helper.d.ts","sourceRoot":"","sources":["../../../src/utils/i18n/module-i18n-helper.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"module-i18n-helper.d.ts","sourceRoot":"","sources":["../../../src/utils/i18n/module-i18n-helper.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAsChD,eAAO,MAAM,0CAA0C,YAAa,OAAO,KAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAS7F,CAAC"}
|
|
@@ -1,33 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.extractInternalI18nPropertyKeysFromModules =
|
|
3
|
+
exports.extractInternalI18nPropertyKeysFromModules = void 0;
|
|
4
|
+
const i18n_1 = require("@forge/i18n");
|
|
5
|
+
const INTERNAL_I18N_PROPERTY_KEY_SUFFIX = '__i18n';
|
|
4
6
|
const isObject = (value) => {
|
|
5
7
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
6
8
|
};
|
|
7
|
-
const isI18nValue = (value) => {
|
|
8
|
-
return typeof value?.i18n === 'string';
|
|
9
|
-
};
|
|
10
|
-
const getI18nKeysFromObject = (obj) => {
|
|
11
|
-
const visited = new Set();
|
|
12
|
-
const visit = (value, i18nPath) => {
|
|
13
|
-
if (!isObject(value) || visited.has(value)) {
|
|
14
|
-
return [];
|
|
15
|
-
}
|
|
16
|
-
visited.add(value);
|
|
17
|
-
return Object.entries(value).flatMap(([propKey, propValue]) => {
|
|
18
|
-
const currentPath = [...i18nPath, propKey];
|
|
19
|
-
if (isI18nValue(propValue)) {
|
|
20
|
-
return [{ propertyPath: currentPath, key: propValue.i18n }];
|
|
21
|
-
}
|
|
22
|
-
else if (Array.isArray(propValue)) {
|
|
23
|
-
return propValue.flatMap((item) => visit(item, currentPath));
|
|
24
|
-
}
|
|
25
|
-
return visit(propValue, currentPath);
|
|
26
|
-
});
|
|
27
|
-
};
|
|
28
|
-
return visit(obj, []);
|
|
29
|
-
};
|
|
30
|
-
const INTERNAL_I18N_PROPERTY_KEY_SUFFIX = '__i18n';
|
|
31
9
|
const isInternalI18nPropertyKey = (key) => {
|
|
32
10
|
return key.length > INTERNAL_I18N_PROPERTY_KEY_SUFFIX.length && key.endsWith(INTERNAL_I18N_PROPERTY_KEY_SUFFIX);
|
|
33
11
|
};
|
|
@@ -53,39 +31,9 @@ const getInternalI18nPropertyKeysFromObject = (obj) => {
|
|
|
53
31
|
};
|
|
54
32
|
return visit(obj);
|
|
55
33
|
};
|
|
56
|
-
const getAllModuleEntries = (modules) => {
|
|
57
|
-
return Object.entries(modules).flatMap(([moduleKey, moduleEntries]) => {
|
|
58
|
-
if (moduleEntries && Array.isArray(moduleEntries) && moduleEntries.length > 0) {
|
|
59
|
-
return moduleEntries.map((moduleEntry) => [moduleEntry, moduleKey]);
|
|
60
|
-
}
|
|
61
|
-
return [];
|
|
62
|
-
});
|
|
63
|
-
};
|
|
64
|
-
const extractI18nPropertiesFromModules = (modules) => {
|
|
65
|
-
const moduleI18nProperties = [];
|
|
66
|
-
for (const moduleEntry of getAllModuleEntries(modules)) {
|
|
67
|
-
const i18nKeysForEntryValue = getI18nKeysFromObject(moduleEntry[0]);
|
|
68
|
-
for (const i18nObj of i18nKeysForEntryValue) {
|
|
69
|
-
moduleI18nProperties.push({ moduleName: moduleEntry[1], ...i18nObj });
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
return moduleI18nProperties;
|
|
73
|
-
};
|
|
74
|
-
exports.extractI18nPropertiesFromModules = extractI18nPropertiesFromModules;
|
|
75
|
-
const extractI18nKeysFromModules = (modules) => {
|
|
76
|
-
const i18nKeys = new Set();
|
|
77
|
-
for (const moduleEntry of getAllModuleEntries(modules)) {
|
|
78
|
-
const i18nKeysForEntryValue = getI18nKeysFromObject(moduleEntry[0]);
|
|
79
|
-
for (const { key } of i18nKeysForEntryValue) {
|
|
80
|
-
i18nKeys.add(key);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
return i18nKeys.size > 0 ? Array.from(i18nKeys) : [];
|
|
84
|
-
};
|
|
85
|
-
exports.extractI18nKeysFromModules = extractI18nKeysFromModules;
|
|
86
34
|
const extractInternalI18nPropertyKeysFromModules = (modules) => {
|
|
87
35
|
const i18nKeys = new Set();
|
|
88
|
-
for (const [moduleEntryObject, moduleKey] of
|
|
36
|
+
for (const [moduleEntryObject, moduleKey] of (0, i18n_1.getI18nSupportedModuleEntries)(modules)) {
|
|
89
37
|
const i18nKeysForEntryValue = getInternalI18nPropertyKeysFromObject(moduleEntryObject);
|
|
90
38
|
for (const key of i18nKeysForEntryValue) {
|
|
91
39
|
i18nKeys.add(`${key},${moduleKey}`);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ForgeSupportedLocaleCode as ExpectedForgeSupportedLocaleCode } from '@forge/i18n';
|
|
2
|
+
import { ForgeSupportedLocaleCode as ActualForgeSupportedLocaleCode } from '../../schema/manifest';
|
|
3
|
+
declare type IsSameType<T, U> = T extends U ? (U extends T ? true : false) : false;
|
|
4
|
+
declare type AreForgeSupportedLocaleCodesConsistent = IsSameType<ExpectedForgeSupportedLocaleCode, ActualForgeSupportedLocaleCode>;
|
|
5
|
+
export declare const __supportedForgeLocaleCodeConsistencyCheck: AreForgeSupportedLocaleCodesConsistent;
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=type-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-check.d.ts","sourceRoot":"","sources":["../../../src/utils/i18n/type-check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,IAAI,gCAAgC,EAAE,MAAM,aAAa,CAAC;AAC3F,OAAO,EAAE,wBAAwB,IAAI,8BAA8B,EAAE,MAAM,uBAAuB,CAAC;AAEnG,aAAK,UAAU,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC;AAE3E,aAAK,sCAAsC,GAAG,UAAU,CACtD,gCAAgC,EAChC,8BAA8B,CAC/B,CAAC;AAEF,eAAO,MAAM,0CAA0C,EAAE,sCAA6C,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translations-validator.d.ts","sourceRoot":"","sources":["../../src/validators/translations-validator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"translations-validator.d.ts","sourceRoot":"","sources":["../../src/validators/translations-validator.ts"],"names":[],"mappings":"AAOA,OAAO,EAA+C,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAItG,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAmB,MAAM,UAAU,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAM3D,qBAAa,qBACX,YAAW,kBAAkB,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,EAAE,cAAc,CAAC;IAEzF,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,GAAG,CAA8D;IAEzE,OAAO,CAAC,8BAA8B;IA4CtC,OAAO,CAAC,6BAA6B;IAwCrC,OAAO,CAAC,mBAAmB;IAwB3B,OAAO,CAAC,gCAAgC;IAoBxC,OAAO,CAAC,UAAU;IAUlB,OAAO,CAAC,qBAAqB;IA4B7B,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,wBAAwB;IAiDhC,OAAO,CAAC,oBAAoB;IA2B5B,OAAO,CAAC,uBAAuB;IAW/B,OAAO,CAAC,iCAAiC;IAwBzC,OAAO,CAAC,0BAA0B;IAalC,OAAO,CAAC,4CAA4C;IAe9C,QAAQ,CACZ,QAAQ,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,GACnD,OAAO,CAAC,wBAAwB,CAAC,cAAc,CAAC,CAAC;CA0BrD"}
|
|
@@ -6,6 +6,7 @@ const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
|
6
6
|
const path_1 = require("path");
|
|
7
7
|
const lodash_1 = require("lodash");
|
|
8
8
|
const ajv_1 = tslib_1.__importDefault(require("ajv"));
|
|
9
|
+
const i18n_1 = require("@forge/i18n");
|
|
9
10
|
const manifest_schema_json_1 = tslib_1.__importDefault(require("../schema/manifest-schema.json"));
|
|
10
11
|
const text_1 = require("../text");
|
|
11
12
|
const text_2 = require("../text");
|
|
@@ -51,36 +52,29 @@ class TranslationsValidator {
|
|
|
51
52
|
}
|
|
52
53
|
ensureValidFallbackDefinition(validationErrors, manifest) {
|
|
53
54
|
const { resources, fallback } = manifest.yamlContent.translations;
|
|
54
|
-
const defaultLanguage = fallback.default;
|
|
55
55
|
const resourcesSet = new Set(resources.map((resource) => resource.key));
|
|
56
|
-
const
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
const fallbackLocales = new Set(Object.values(fallback).flatMap((locales) => Array.isArray(locales) ? locales : [locales]));
|
|
57
|
+
for (const fallbackLocale of fallbackLocales) {
|
|
58
|
+
if (!resourcesSet.has(fallbackLocale)) {
|
|
59
|
+
const targetLocale = Object.entries(fallback).find(([, locales]) => locales === fallbackLocale || locales.includes(fallbackLocale))?.[0];
|
|
60
60
|
validationErrors.push({
|
|
61
|
-
message: text_1.errors.translations.missingTranslationsJsonFile(
|
|
61
|
+
message: text_1.errors.translations.missingTranslationsJsonFile(fallbackLocale),
|
|
62
62
|
reference: text_2.References.SchemaError,
|
|
63
63
|
level: 'error',
|
|
64
|
-
...(0, utils_1.findPosition)(
|
|
64
|
+
...(0, utils_1.findPosition)(`${targetLocale}:`, manifest.yamlContentByLine)
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
validationErrors.push({
|
|
79
|
-
message: text_1.errors.translations.duplicateFallbackConfig(duplicate),
|
|
80
|
-
reference: text_2.References.SchemaError,
|
|
81
|
-
level: 'error',
|
|
82
|
-
...(0, utils_1.findPosition)(duplicate, manifest.yamlContentByLine)
|
|
83
|
-
});
|
|
68
|
+
for (const [targetLocale, fallbackLocales] of Object.entries(fallback)) {
|
|
69
|
+
const locales = [targetLocale, ...(Array.isArray(fallbackLocales) ? fallbackLocales : [fallbackLocales])];
|
|
70
|
+
if (locales.length !== new Set(locales).size) {
|
|
71
|
+
validationErrors.push({
|
|
72
|
+
message: text_1.errors.translations.duplicateFallbackConfig(targetLocale),
|
|
73
|
+
reference: text_2.References.SchemaError,
|
|
74
|
+
level: 'error',
|
|
75
|
+
...(0, utils_1.findPosition)(`${targetLocale}:`, manifest.yamlContentByLine)
|
|
76
|
+
});
|
|
77
|
+
}
|
|
84
78
|
}
|
|
85
79
|
}
|
|
86
80
|
getAllLocalesLookup(validationErrors, i18nKeys, translationsLookup, manifest) {
|
|
@@ -99,7 +93,7 @@ class TranslationsValidator {
|
|
|
99
93
|
}
|
|
100
94
|
ensureI18nKeysExistInDefaultJson(validationErrors, i18nKeys, translationsLookup, locale, manifest) {
|
|
101
95
|
for (const i18nKey of i18nKeys) {
|
|
102
|
-
const i18nValue = (0,
|
|
96
|
+
const i18nValue = (0, i18n_1.getTranslationValue)(translationsLookup, i18nKey, locale);
|
|
103
97
|
if (!i18nValue) {
|
|
104
98
|
validationErrors.push({
|
|
105
99
|
message: text_1.errors.translations.i18nKeyNotFound(i18nKey),
|
|
@@ -112,7 +106,7 @@ class TranslationsValidator {
|
|
|
112
106
|
}
|
|
113
107
|
getI18nMap(i18nKeys, translationsLookup, locale) {
|
|
114
108
|
return i18nKeys.reduce((i18nMap, key) => {
|
|
115
|
-
const i18nValue = (0,
|
|
109
|
+
const i18nValue = (0, i18n_1.getTranslationValue)(translationsLookup, key, locale);
|
|
116
110
|
if (i18nValue) {
|
|
117
111
|
i18nMap.set(key, i18nValue);
|
|
118
112
|
}
|
|
@@ -252,7 +246,7 @@ class TranslationsValidator {
|
|
|
252
246
|
manifestObject: manifest
|
|
253
247
|
};
|
|
254
248
|
}
|
|
255
|
-
const moduleI18nProperties = (0,
|
|
249
|
+
const moduleI18nProperties = (0, i18n_1.extractI18nPropertiesFromModules)(manifest?.typedContent?.modules ?? {});
|
|
256
250
|
const i18nKeys = moduleI18nProperties.map((i18nConfig) => i18nConfig.key);
|
|
257
251
|
const i18nConfig = manifest?.yamlContent?.translations;
|
|
258
252
|
if (!i18nConfig) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forge/manifest",
|
|
3
|
-
"version": "7.7.0-next.
|
|
3
|
+
"version": "7.7.0-next.13",
|
|
4
4
|
"description": "Definitions and validations of the Forge manifest",
|
|
5
5
|
"main": "out/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"author": "Atlassian",
|
|
25
25
|
"license": "UNLICENSED",
|
|
26
26
|
"dependencies": {
|
|
27
|
+
"@forge/i18n": "0.0.1-next.12",
|
|
27
28
|
"@sentry/node": "7.100.1",
|
|
28
29
|
"ajv": "^8.12.0",
|
|
29
30
|
"ajv-formats": "2.1.1",
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { type ForgeSupportedLocaleCode } from '../../schema/manifest';
|
|
2
|
-
interface TranslationContent {
|
|
3
|
-
[key: string]: string | TranslationContent;
|
|
4
|
-
}
|
|
5
|
-
declare type TranslationContentByLocaleCode = {
|
|
6
|
-
[key in ForgeSupportedLocaleCode]?: TranslationContent;
|
|
7
|
-
};
|
|
8
|
-
export declare const getTranslationValue: (translationLookup: TranslationContentByLocaleCode, i18nKey: string, locale: ForgeSupportedLocaleCode) => string | null;
|
|
9
|
-
export declare const getTranslationValueFromContent: (translationContent: TranslationContent, i18nKey: string) => string | null;
|
|
10
|
-
export {};
|
|
11
|
-
//# sourceMappingURL=translation-value-getter.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"translation-value-getter.d.ts","sourceRoot":"","sources":["../../../src/utils/i18n/translation-value-getter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAEtE,UAAU,kBAAkB;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,kBAAkB,CAAC;CAC5C;AAED,aAAK,8BAA8B,GAAG;KACnC,GAAG,IAAI,wBAAwB,CAAC,CAAC,EAAE,kBAAkB;CACvD,CAAC;AAIF,eAAO,MAAM,mBAAmB,sBACX,8BAA8B,WACxC,MAAM,UACP,wBAAwB,KAC/B,MAAM,GAAG,IAMX,CAAC;AAEF,eAAO,MAAM,8BAA8B,uBACrB,kBAAkB,WAC7B,MAAM,KACd,MAAM,GAAG,IAUX,CAAC"}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getTranslationValueFromContent = exports.getTranslationValue = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const get_1 = tslib_1.__importDefault(require("lodash/get"));
|
|
6
|
-
const getTranslationValue = (translationLookup, i18nKey, locale) => {
|
|
7
|
-
const translation = translationLookup[locale];
|
|
8
|
-
if (!translation) {
|
|
9
|
-
return null;
|
|
10
|
-
}
|
|
11
|
-
return (0, exports.getTranslationValueFromContent)(translation, i18nKey);
|
|
12
|
-
};
|
|
13
|
-
exports.getTranslationValue = getTranslationValue;
|
|
14
|
-
const getTranslationValueFromContent = (translationContent, i18nKey) => {
|
|
15
|
-
let translationValue = translationContent[i18nKey];
|
|
16
|
-
if (!translationValue) {
|
|
17
|
-
const keyTokens = i18nKey.split('.');
|
|
18
|
-
if (keyTokens.length > 1) {
|
|
19
|
-
translationValue = (0, get_1.default)(translationContent, keyTokens, null);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
return typeof translationValue === 'string' ? translationValue : null;
|
|
23
|
-
};
|
|
24
|
-
exports.getTranslationValueFromContent = getTranslationValueFromContent;
|