@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 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,3 +1,2 @@
1
1
  export * from './module-i18n-helper';
2
- export * from './translation-value-getter';
3
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/i18n/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/i18n/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC"}
@@ -2,4 +2,3 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  tslib_1.__exportStar(require("./module-i18n-helper"), exports);
5
- tslib_1.__exportStar(require("./translation-value-getter"), exports);
@@ -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":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAEhD,oBAAY,oBAAoB,GAAG;IACjC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;CACb,EAAE,CAAC;AA8EJ,eAAO,MAAM,gCAAgC,YAAa,OAAO,yBAWhE,CAAC;AAGF,eAAO,MAAM,0BAA0B,YAAa,OAAO,KAAG,MAAM,EAWnE,CAAC;AAEF,eAAO,MAAM,0CAA0C,YAAa,OAAO,KAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAS7F,CAAC"}
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 = exports.extractI18nKeysFromModules = exports.extractI18nPropertiesFromModules = void 0;
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 getAllModuleEntries(modules)) {
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"}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.__supportedForgeLocaleCodeConsistencyCheck = void 0;
4
+ exports.__supportedForgeLocaleCodeConsistencyCheck = true;
@@ -1 +1 @@
1
- {"version":3,"file":"translations-validator.d.ts","sourceRoot":"","sources":["../../src/validators/translations-validator.ts"],"names":[],"mappings":"AAKA,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;AAW3D,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;IA+CrC,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"}
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 fallbackLanguages = Object.keys(fallback).filter((fallbackLanguage) => fallbackLanguage !== 'default');
57
- const allFallbackLanguagesSet = new Set([defaultLanguage, ...fallbackLanguages]);
58
- for (const fallbackLanguage of allFallbackLanguagesSet) {
59
- if (!resourcesSet.has(fallbackLanguage)) {
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(fallbackLanguage),
61
+ message: text_1.errors.translations.missingTranslationsJsonFile(fallbackLocale),
62
62
  reference: text_2.References.SchemaError,
63
63
  level: 'error',
64
- ...(0, utils_1.findPosition)(fallbackLanguage === defaultLanguage ? `default: ${fallbackLanguage}` : `${fallbackLanguage}:`, manifest.yamlContentByLine)
64
+ ...(0, utils_1.findPosition)(`${targetLocale}:`, manifest.yamlContentByLine)
65
65
  });
66
66
  }
67
67
  }
68
- const allLanguagesList = [
69
- defaultLanguage,
70
- ...fallbackLanguages,
71
- ...fallbackLanguages.flatMap((language) => fallback[language])
72
- ];
73
- const [, duplicates] = allLanguagesList.reduce(([languageSet, duplicates], language) => {
74
- languageSet.has(language) ? duplicates.add(language) : languageSet.add(language);
75
- return [languageSet, duplicates];
76
- }, [new Set(), new Set()]);
77
- for (const duplicate of duplicates) {
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, utils_1.getTranslationValue)(translationsLookup, i18nKey, locale);
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, utils_1.getTranslationValue)(translationsLookup, key, locale);
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, utils_1.extractI18nPropertiesFromModules)(manifest?.typedContent?.modules ?? {});
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.12",
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;