@sap-ux/project-access 2.2.2 → 2.3.0
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/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/project/access.js +12 -1
- package/dist/project/i18n/i18n.js +107 -35
- package/dist/project/i18n/index.d.ts +1 -1
- package/dist/project/i18n/index.js +1 -1
- package/dist/project/i18n/read.js +49 -5
- package/dist/project/i18n/write.d.ts +12 -1
- package/dist/project/i18n/write.js +18 -1
- package/dist/project/index.d.ts +1 -1
- package/dist/project/index.js +1 -1
- package/dist/types/access/index.d.ts +9 -0
- package/dist/types/info/index.d.ts +10 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { FileName, DirName, FioriToolsSettings, MinCdsPluginUi5Version, MinCdsVersion, fioriToolsDirectory } from './constants.js';
|
|
2
2
|
export { getFilePaths, findFilesByExtension } from './file/index.js';
|
|
3
3
|
export { normalizePath } from './path/index.js';
|
|
4
|
-
export { addPackageDevDependency, clearCdsModuleCache, createApplicationAccess, createProjectAccess, deleteCapApp, filterDataSourcesByType, findAllApps, findCapProjectRoot, findCapProjects, findFioriArtifacts, findProjectRoot, findRootsForPath, getAllUi5YamlFileNames, getAppRootFromWebappPath, getAppProgrammingLanguage, getAppType, getCapCustomPaths, getCapEnvironment, getCapModelAndServices, getCapServiceName, getCapProjectType, getCdsFiles, getCdsRoots, getCdsServices, getCapI18nFolderNames, getSpecification, getSpecificationModuleFromCache, getSpecificationPath, getI18nPropertiesPaths, getI18nBundles, getMinUI5VersionFromManifest, getMinUI5VersionAsArray, getMinimumUI5Version, getMtaPath, getMockServerConfig, getMockDataPath, getNodeModulesPath, getPathMappings, getProject, getProjectType, getWebappPath, hasUI5CliV3, isCapProject, isCapJavaProject, isCapNodeJsProject, loadModuleFromProject, readCapServiceMetadataEdmx, readUi5Yaml, refreshSpecificationDistTags, toReferenceUri, updatePackageScript, getWorkspaceInfo, hasMinCdsVersion, checkCdsUi5PluginEnabled, readFlexChanges, processServices, getMainService, getGlobalCdsHomePath, isUI5IdUnique, getUsedEntitiesFromManifest, resolveApplicationTitle } from './project/index.js';
|
|
4
|
+
export { addPackageDevDependency, clearCdsModuleCache, createApplicationAccess, createProjectAccess, deleteCapApp, filterDataSourcesByType, findAllApps, findCapProjectRoot, findCapProjects, findFioriArtifacts, findProjectRoot, findRootsForPath, getAllUi5YamlFileNames, getAppRootFromWebappPath, getAppProgrammingLanguage, getAppType, getCapCustomPaths, getCapEnvironment, getCapModelAndServices, getCapServiceName, getCapProjectType, getCdsFiles, getCdsRoots, getCdsServices, getCapI18nFolderNames, getSpecification, getSpecificationModuleFromCache, getSpecificationPath, getI18nPropertiesPaths, getI18nBundles, createI18nEntriesAtPath, getMinUI5VersionFromManifest, getMinUI5VersionAsArray, getMinimumUI5Version, getMtaPath, getMockServerConfig, getMockDataPath, getNodeModulesPath, getPathMappings, getProject, getProjectType, getWebappPath, hasUI5CliV3, isCapProject, isCapJavaProject, isCapNodeJsProject, loadModuleFromProject, readCapServiceMetadataEdmx, readUi5Yaml, refreshSpecificationDistTags, toReferenceUri, updatePackageScript, getWorkspaceInfo, hasMinCdsVersion, checkCdsUi5PluginEnabled, readFlexChanges, processServices, getMainService, getGlobalCdsHomePath, isUI5IdUnique, getUsedEntitiesFromManifest, resolveApplicationTitle } from './project/index.js';
|
|
5
5
|
export type { UsedEntity } from './project/index.js';
|
|
6
6
|
export { execNpmCommand } from './command/npm-command.js';
|
|
7
7
|
export * from './types/index.js';
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { FileName, DirName, FioriToolsSettings, MinCdsPluginUi5Version, MinCdsVersion, fioriToolsDirectory } from './constants.js';
|
|
2
2
|
export { getFilePaths, findFilesByExtension } from './file/index.js';
|
|
3
3
|
export { normalizePath } from './path/index.js';
|
|
4
|
-
export { addPackageDevDependency, clearCdsModuleCache, createApplicationAccess, createProjectAccess, deleteCapApp, filterDataSourcesByType, findAllApps, findCapProjectRoot, findCapProjects, findFioriArtifacts, findProjectRoot, findRootsForPath, getAllUi5YamlFileNames, getAppRootFromWebappPath, getAppProgrammingLanguage, getAppType, getCapCustomPaths, getCapEnvironment, getCapModelAndServices, getCapServiceName, getCapProjectType, getCdsFiles, getCdsRoots, getCdsServices, getCapI18nFolderNames, getSpecification, getSpecificationModuleFromCache, getSpecificationPath, getI18nPropertiesPaths, getI18nBundles, getMinUI5VersionFromManifest, getMinUI5VersionAsArray, getMinimumUI5Version, getMtaPath, getMockServerConfig, getMockDataPath, getNodeModulesPath, getPathMappings, getProject, getProjectType, getWebappPath, hasUI5CliV3, isCapProject, isCapJavaProject, isCapNodeJsProject, loadModuleFromProject, readCapServiceMetadataEdmx, readUi5Yaml, refreshSpecificationDistTags, toReferenceUri, updatePackageScript, getWorkspaceInfo, hasMinCdsVersion, checkCdsUi5PluginEnabled, readFlexChanges, processServices, getMainService, getGlobalCdsHomePath, isUI5IdUnique, getUsedEntitiesFromManifest, resolveApplicationTitle } from './project/index.js';
|
|
4
|
+
export { addPackageDevDependency, clearCdsModuleCache, createApplicationAccess, createProjectAccess, deleteCapApp, filterDataSourcesByType, findAllApps, findCapProjectRoot, findCapProjects, findFioriArtifacts, findProjectRoot, findRootsForPath, getAllUi5YamlFileNames, getAppRootFromWebappPath, getAppProgrammingLanguage, getAppType, getCapCustomPaths, getCapEnvironment, getCapModelAndServices, getCapServiceName, getCapProjectType, getCdsFiles, getCdsRoots, getCdsServices, getCapI18nFolderNames, getSpecification, getSpecificationModuleFromCache, getSpecificationPath, getI18nPropertiesPaths, getI18nBundles, createI18nEntriesAtPath, getMinUI5VersionFromManifest, getMinUI5VersionAsArray, getMinimumUI5Version, getMtaPath, getMockServerConfig, getMockDataPath, getNodeModulesPath, getPathMappings, getProject, getProjectType, getWebappPath, hasUI5CliV3, isCapProject, isCapJavaProject, isCapNodeJsProject, loadModuleFromProject, readCapServiceMetadataEdmx, readUi5Yaml, refreshSpecificationDistTags, toReferenceUri, updatePackageScript, getWorkspaceInfo, hasMinCdsVersion, checkCdsUi5PluginEnabled, readFlexChanges, processServices, getMainService, getGlobalCdsHomePath, isUI5IdUnique, getUsedEntitiesFromManifest, resolveApplicationTitle } from './project/index.js';
|
|
5
5
|
export { execNpmCommand } from './command/npm-command.js';
|
|
6
6
|
export * from './types/index.js';
|
|
7
7
|
export { checkDependencies, getReuseLibs } from './library/index.js';
|
package/dist/project/access.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { join, relative } from 'node:path';
|
|
2
|
-
import { getI18nBundles, getI18nPropertiesPaths, createCapI18nEntries, createManifestI18nEntries, createUI5I18nEntries, createAnnotationI18nEntries } from './i18n/index.js';
|
|
2
|
+
import { getI18nBundles, getI18nPropertiesPaths, createCapI18nEntries, createManifestI18nEntries, createUI5I18nEntries, createAnnotationI18nEntries, createI18nEntriesAtPath } from './i18n/index.js';
|
|
3
3
|
import { getProject } from './info.js';
|
|
4
4
|
import { findAllApps } from './search.js';
|
|
5
5
|
import { readFile, readJSON, updateManifestJSON, updatePackageJSON } from '../file/index.js';
|
|
@@ -102,6 +102,17 @@ class ApplicationAccessImp {
|
|
|
102
102
|
createCapI18nEntries(filePath, newI18nEntries) {
|
|
103
103
|
return createCapI18nEntries(this.project.root, filePath, newI18nEntries, this.options?.fs);
|
|
104
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Maintains new translation entries at a specific i18n properties file path.
|
|
107
|
+
* Use this when the target file is already known (e.g. chosen by the user from a picker).
|
|
108
|
+
*
|
|
109
|
+
* @param filePath absolute path to the target `.properties` file
|
|
110
|
+
* @param newEntries translation entries to write
|
|
111
|
+
* @returns boolean or exception
|
|
112
|
+
*/
|
|
113
|
+
createI18nEntriesAtPath(filePath, newEntries) {
|
|
114
|
+
return createI18nEntriesAtPath(this.project.root, filePath, newEntries, this.options?.fs);
|
|
115
|
+
}
|
|
105
116
|
/**
|
|
106
117
|
* Return the application id of this app, which is the relative path from the project root
|
|
107
118
|
* to the app root.
|
|
@@ -16,10 +16,17 @@ export async function getI18nPropertiesPaths(manifestPath, manifest, memFs) {
|
|
|
16
16
|
'sap.app': join(manifestFolder, relativeI18nPropertiesPaths['sap.app']),
|
|
17
17
|
models: {}
|
|
18
18
|
};
|
|
19
|
+
if (relativeI18nPropertiesPaths['sap.app.fallbackLocale']) {
|
|
20
|
+
i18nPropertiesPaths['sap.app.fallbackLocale'] = join(manifestFolder, relativeI18nPropertiesPaths['sap.app.fallbackLocale']);
|
|
21
|
+
}
|
|
19
22
|
for (const modelKey in relativeI18nPropertiesPaths.models) {
|
|
23
|
+
const relativeModelPaths = relativeI18nPropertiesPaths.models[modelKey];
|
|
20
24
|
i18nPropertiesPaths.models[modelKey] = {
|
|
21
|
-
path: join(manifestFolder,
|
|
25
|
+
path: join(manifestFolder, relativeModelPaths.path)
|
|
22
26
|
};
|
|
27
|
+
if (relativeModelPaths.fallbackLocalePath) {
|
|
28
|
+
i18nPropertiesPaths.models[modelKey].fallbackLocalePath = join(manifestFolder, relativeModelPaths.fallbackLocalePath);
|
|
29
|
+
}
|
|
23
30
|
}
|
|
24
31
|
return i18nPropertiesPaths;
|
|
25
32
|
}
|
|
@@ -31,10 +38,45 @@ export async function getI18nPropertiesPaths(manifestPath, manifest, memFs) {
|
|
|
31
38
|
* @returns - paths to i18n.properties files from sap.app and models
|
|
32
39
|
*/
|
|
33
40
|
export function getRelativeI18nPropertiesPaths(manifest) {
|
|
34
|
-
|
|
35
|
-
|
|
41
|
+
const appPath = getI18nAppPath(manifest);
|
|
42
|
+
const appFallbackLocalePath = getI18nAppFallbackLocalePath(manifest, appPath);
|
|
43
|
+
const result = {
|
|
44
|
+
'sap.app': appPath,
|
|
36
45
|
models: getI18nModelPaths(manifest)
|
|
37
46
|
};
|
|
47
|
+
if (appFallbackLocalePath) {
|
|
48
|
+
result['sap.app.fallbackLocale'] = appFallbackLocalePath;
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Computes the fallback locale variant of a base i18n file path, e.g. "i18n/i18n.properties" + "en" yields "i18n/i18n_en.properties".
|
|
54
|
+
*
|
|
55
|
+
* @param basePath - base i18n file path
|
|
56
|
+
* @param locale - fallback locale string (e.g. "en", "de")
|
|
57
|
+
* @returns - path to the fallback locale file
|
|
58
|
+
*/
|
|
59
|
+
function computeFallbackLocalePath(basePath, locale) {
|
|
60
|
+
const ext = '.properties';
|
|
61
|
+
const stem = basePath.endsWith(ext) ? basePath.slice(0, -ext.length) : basePath;
|
|
62
|
+
return `${stem}_${locale}${ext}`;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get the fallback locale i18n path from sap.app.i18n part of the manifest.
|
|
66
|
+
*
|
|
67
|
+
* @param manifest - parsed content of manifest.json
|
|
68
|
+
* @param appPath - resolved base i18n path for sap.app
|
|
69
|
+
* @returns - fallback locale path, or undefined if not configured
|
|
70
|
+
*/
|
|
71
|
+
function getI18nAppFallbackLocalePath(manifest, appPath) {
|
|
72
|
+
const i18n = manifest?.['sap.app']?.i18n;
|
|
73
|
+
if (i18n !== null && typeof i18n === 'object') {
|
|
74
|
+
const fallbackLocale = i18n.fallbackLocale;
|
|
75
|
+
if (typeof fallbackLocale === 'string' && fallbackLocale && /^[A-Za-z0-9_-]+$/.test(fallbackLocale)) {
|
|
76
|
+
return computeFallbackLocalePath(appPath, fallbackLocale);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return undefined;
|
|
38
80
|
}
|
|
39
81
|
/**
|
|
40
82
|
* Get the i18n path from sap.app.i18n part of the manifest.
|
|
@@ -52,61 +94,91 @@ function getI18nAppPath(manifest) {
|
|
|
52
94
|
if (typeof manifest?.['sap.app']?.i18n === 'string') {
|
|
53
95
|
return join(manifest['sap.app'].i18n);
|
|
54
96
|
}
|
|
55
|
-
|
|
97
|
+
const i18nObj = manifest?.['sap.app']?.i18n;
|
|
98
|
+
if (i18nObj !== null && typeof i18nObj === 'object') {
|
|
56
99
|
// bundleName wins over `bundleUrl`
|
|
57
|
-
if ('bundleName' in
|
|
58
|
-
// module name is in dot notation
|
|
59
|
-
const
|
|
60
|
-
const
|
|
100
|
+
if ('bundleName' in i18nObj) {
|
|
101
|
+
// module name is in dot notation; strip appId as a prefix
|
|
102
|
+
const bundleName = i18nObj.bundleName;
|
|
103
|
+
const appId = manifest['sap.app'].id ?? '';
|
|
104
|
+
const suffix = appId && bundleName.startsWith(appId) ? bundleName.slice(appId.length) : bundleName;
|
|
105
|
+
if (!suffix) {
|
|
106
|
+
return defaultPath;
|
|
107
|
+
}
|
|
108
|
+
const i18nPath = `${join(...suffix.split('.'))}.properties`;
|
|
61
109
|
return join(i18nPath);
|
|
62
110
|
}
|
|
63
|
-
if ('bundleUrl' in
|
|
64
|
-
return join(
|
|
111
|
+
if ('bundleUrl' in i18nObj) {
|
|
112
|
+
return join(i18nObj.bundleUrl);
|
|
65
113
|
}
|
|
66
114
|
}
|
|
67
115
|
// default
|
|
68
116
|
return defaultPath;
|
|
69
117
|
}
|
|
70
118
|
/**
|
|
71
|
-
*
|
|
72
|
-
* By default the model used for internationalization in the UI is 'i18n'. For
|
|
73
|
-
* internationalization of annotations the model is '@18n'.
|
|
119
|
+
* Resolves the i18n file path from a resource model's settings object.
|
|
74
120
|
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
121
|
+
* @param appId - application id from sap.app namespace
|
|
122
|
+
* @param settings - resource model settings object
|
|
123
|
+
* @param settings.bundleName - bundle name in dot notation (e.g. "sample.app.i18n")
|
|
124
|
+
* @param settings.bundleUrl - bundle URL path (e.g. "i18n/i18n.properties")
|
|
125
|
+
* @returns - resolved relative path, or undefined if it cannot be determined
|
|
126
|
+
*/
|
|
127
|
+
function extractBundlePath(appId, settings) {
|
|
128
|
+
if (settings.bundleName) {
|
|
129
|
+
// Strip appId as a prefix when present; fall back to full bundleName otherwise.
|
|
130
|
+
// Prefix-strip is safer than String.replace which would remove the first occurrence anywhere in the string.
|
|
131
|
+
const suffix = appId && settings.bundleName.startsWith(appId)
|
|
132
|
+
? settings.bundleName.slice(appId.length)
|
|
133
|
+
: settings.bundleName;
|
|
134
|
+
if (!suffix) {
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
return `${join(...suffix.split('.'))}.properties`;
|
|
138
|
+
}
|
|
139
|
+
if (settings.bundleUrl) {
|
|
140
|
+
return join(settings.bundleUrl);
|
|
141
|
+
}
|
|
142
|
+
return undefined;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Extracts and validates the `fallbackLocale` from a UI5 resource model settings object.
|
|
146
|
+
* Only alphanumeric, dash, and underscore characters are accepted (e.g. "en", "en-US").
|
|
79
147
|
*
|
|
80
|
-
* @param
|
|
81
|
-
* @returns
|
|
148
|
+
* @param settings - sap.ui5 resource model settings object
|
|
149
|
+
* @returns validated fallback locale string or undefined if invalid/absent
|
|
82
150
|
*/
|
|
151
|
+
function getValidFallbackLocale(settings) {
|
|
152
|
+
const fallbackLocale = settings?.fallbackLocale;
|
|
153
|
+
return typeof fallbackLocale === 'string' && fallbackLocale && /^[A-Za-z0-9_-]+$/.test(fallbackLocale)
|
|
154
|
+
? fallbackLocale
|
|
155
|
+
: undefined;
|
|
156
|
+
}
|
|
83
157
|
function getI18nModelPaths(manifest) {
|
|
84
158
|
const result = {};
|
|
85
159
|
const models = manifest?.['sap.ui5']?.models ?? {};
|
|
86
160
|
const resourceModelKeys = Object.keys(models).filter((key) => models[key].type === 'sap.ui.model.resource.ResourceModel');
|
|
87
161
|
for (const modelKey of resourceModelKeys) {
|
|
88
162
|
const i18nModel = models[modelKey];
|
|
89
|
-
// settings wins over `uri`
|
|
90
163
|
if (i18nModel.settings) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
const i18nPath = `${join(...withoutAppId.split('.'))}.properties`;
|
|
100
|
-
result[modelKey] = { path: join(i18nPath) };
|
|
101
|
-
continue;
|
|
102
|
-
}
|
|
103
|
-
if (i18nModel.settings.bundleUrl) {
|
|
104
|
-
result[modelKey] = { path: join(i18nModel.settings.bundleUrl) };
|
|
164
|
+
const appId = manifest['sap.app']?.id ?? '';
|
|
165
|
+
const path = extractBundlePath(appId, i18nModel.settings);
|
|
166
|
+
if (path) {
|
|
167
|
+
const fallbackLocale = getValidFallbackLocale(i18nModel.settings);
|
|
168
|
+
result[modelKey] = {
|
|
169
|
+
path,
|
|
170
|
+
...(fallbackLocale && { fallbackLocalePath: computeFallbackLocalePath(path, fallbackLocale) })
|
|
171
|
+
};
|
|
105
172
|
continue;
|
|
106
173
|
}
|
|
107
174
|
}
|
|
108
175
|
if (i18nModel.uri) {
|
|
109
|
-
|
|
176
|
+
const path = join(i18nModel.uri);
|
|
177
|
+
const fallbackLocale = getValidFallbackLocale(i18nModel.settings);
|
|
178
|
+
result[modelKey] = {
|
|
179
|
+
path,
|
|
180
|
+
...(fallbackLocale && { fallbackLocalePath: computeFallbackLocalePath(path, fallbackLocale) })
|
|
181
|
+
};
|
|
110
182
|
}
|
|
111
183
|
}
|
|
112
184
|
return result;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { getI18nPropertiesPaths } from './i18n.js';
|
|
2
2
|
export { getCapI18nFolderNames, getI18nBundles } from './read.js';
|
|
3
|
-
export { createManifestI18nEntries, createUI5I18nEntries, createAnnotationI18nEntries, createCapI18nEntries } from './write.js';
|
|
3
|
+
export { createManifestI18nEntries, createUI5I18nEntries, createAnnotationI18nEntries, createCapI18nEntries, createI18nEntriesAtPath } from './write.js';
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { getI18nPropertiesPaths } from './i18n.js';
|
|
2
2
|
export { getCapI18nFolderNames, getI18nBundles } from './read.js';
|
|
3
|
-
export { createManifestI18nEntries, createUI5I18nEntries, createAnnotationI18nEntries, createCapI18nEntries } from './write.js';
|
|
3
|
+
export { createManifestI18nEntries, createUI5I18nEntries, createAnnotationI18nEntries, createCapI18nEntries, createI18nEntriesAtPath } from './write.js';
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
|
@@ -8,11 +8,48 @@ import { getCapEnvironment, getCdsFiles } from '../index.js';
|
|
|
8
8
|
* @param error error to add
|
|
9
9
|
*/
|
|
10
10
|
function addToErrors(result, key, error) {
|
|
11
|
-
|
|
12
|
-
result.errors = {};
|
|
13
|
-
}
|
|
11
|
+
result.errors ??= {};
|
|
14
12
|
result.errors[key] = error;
|
|
15
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Merges a fallback locale bundle into a primary bundle.
|
|
16
|
+
* Skipped when the primary failed with a non-ENOENT error (file exists but unreadable).
|
|
17
|
+
* Clears the primary ENOENT error when the fallback is read successfully.
|
|
18
|
+
* Stores non-ENOENT fallback errors in result.errors instead of throwing.
|
|
19
|
+
*
|
|
20
|
+
* @param result - accumulator for bundles and errors
|
|
21
|
+
* @param primaryKey - error key used to look up the primary error (e.g. 'sap.app')
|
|
22
|
+
* @param current - primary bundle (may be empty if primary failed)
|
|
23
|
+
* @param fallbackPath - path to the fallback locale .properties file
|
|
24
|
+
* @param fs - optional mem-fs-editor instance
|
|
25
|
+
* @returns merged bundle (fallback keys supplemented by primary entries)
|
|
26
|
+
*/
|
|
27
|
+
async function mergeWithFallback(result, primaryKey, current, fallbackPath, fs) {
|
|
28
|
+
const primaryError = result.errors?.[primaryKey];
|
|
29
|
+
if (primaryError && primaryError.code !== 'ENOENT') {
|
|
30
|
+
return current;
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
const fallbackBundle = await getPropertiesI18nBundle(fallbackPath, fs);
|
|
34
|
+
if (primaryError?.code === 'ENOENT') {
|
|
35
|
+
const errors = result.errors;
|
|
36
|
+
if (errors) {
|
|
37
|
+
delete errors[primaryKey];
|
|
38
|
+
if (Object.keys(errors).length === 0) {
|
|
39
|
+
result.errors = undefined;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Primary entries take precedence on key collision
|
|
44
|
+
return { ...fallbackBundle, ...current };
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
if (error.code !== 'ENOENT') {
|
|
48
|
+
addToErrors(result, `${primaryKey}.fallbackLocale`, error);
|
|
49
|
+
}
|
|
50
|
+
return current;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
16
53
|
/**
|
|
17
54
|
* For a given app in project, retrieves i18n bundles for 'sap.app' namespace,`models` of `sap.ui5` namespace and service for cap services.
|
|
18
55
|
*
|
|
@@ -36,7 +73,10 @@ export async function getI18nBundles(root, i18nPropertiesPaths, projectType, fs)
|
|
|
36
73
|
catch (error) {
|
|
37
74
|
addToErrors(result, 'sap.app', error);
|
|
38
75
|
}
|
|
39
|
-
|
|
76
|
+
if (i18nPropertiesPaths['sap.app.fallbackLocale']) {
|
|
77
|
+
result['sap.app'] = await mergeWithFallback(result, 'sap.app', result['sap.app'], i18nPropertiesPaths['sap.app.fallbackLocale'], fs);
|
|
78
|
+
}
|
|
79
|
+
await Promise.all(Object.keys(i18nPropertiesPaths.models).map(async (key) => {
|
|
40
80
|
try {
|
|
41
81
|
result.models[key] = await getPropertiesI18nBundle(i18nPropertiesPaths.models[key].path, fs);
|
|
42
82
|
}
|
|
@@ -45,7 +85,11 @@ export async function getI18nBundles(root, i18nPropertiesPaths, projectType, fs)
|
|
|
45
85
|
result.models[key] = {};
|
|
46
86
|
addToErrors(result, `models.${key}`, error);
|
|
47
87
|
}
|
|
48
|
-
|
|
88
|
+
const fallbackLocalePath = i18nPropertiesPaths.models[key].fallbackLocalePath;
|
|
89
|
+
if (fallbackLocalePath) {
|
|
90
|
+
result.models[key] = await mergeWithFallback(result, `models.${key}`, result.models[key], fallbackLocalePath, fs);
|
|
91
|
+
}
|
|
92
|
+
}));
|
|
49
93
|
if (projectType === 'CAPJava' || projectType === 'CAPNodejs') {
|
|
50
94
|
try {
|
|
51
95
|
const env = await getCapEnvironment(root);
|
|
@@ -64,11 +64,22 @@ export declare function createUI5I18nEntries(root: string, manifestPath: string,
|
|
|
64
64
|
* ```
|
|
65
65
|
*/
|
|
66
66
|
export declare function createAnnotationI18nEntries(root: string, manifestPath: string, i18nPropertiesPaths: I18nPropertiesPaths, newEntries: NewI18nEntry[], fs?: Editor): Promise<boolean>;
|
|
67
|
+
/**
|
|
68
|
+
* Maintains new translation entries at a specific i18n properties file path.
|
|
69
|
+
* Use this when the target file is already known (e.g. chosen by the user from a picker).
|
|
70
|
+
*
|
|
71
|
+
* @param root project root
|
|
72
|
+
* @param filePath absolute path to the target `.properties` file
|
|
73
|
+
* @param newEntries translation entries to write
|
|
74
|
+
* @param fs optional `mem-fs-editor` instance
|
|
75
|
+
* @returns boolean or exception
|
|
76
|
+
*/
|
|
77
|
+
export declare function createI18nEntriesAtPath(root: string, filePath: string, newEntries: NewI18nEntry[], fs?: Editor): Promise<boolean>;
|
|
67
78
|
/**
|
|
68
79
|
* Maintains new translation entries in an existing i18n file or in a new i18n properties file if it does not exist.
|
|
69
80
|
*
|
|
70
81
|
* @param root project root
|
|
71
|
-
* @param i18nPropertiesPaths paths to `.properties` file
|
|
82
|
+
* @param i18nPropertiesPaths paths to `.properties` file
|
|
72
83
|
* @param newEntries translation entries to write in the `.properties` file
|
|
73
84
|
* @param fs optional `mem-fs-editor` instance. If provided, `mem-fs-editor` api is used instead of `fs` of node
|
|
74
85
|
* @returns boolean or exception
|
|
@@ -118,11 +118,28 @@ export async function createUI5I18nEntries(root, manifestPath, i18nPropertiesPat
|
|
|
118
118
|
export async function createAnnotationI18nEntries(root, manifestPath, i18nPropertiesPaths, newEntries, fs) {
|
|
119
119
|
return createUI5I18nEntriesBase(root, manifestPath, i18nPropertiesPaths, newEntries, '@i18n', fs);
|
|
120
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* Maintains new translation entries at a specific i18n properties file path.
|
|
123
|
+
* Use this when the target file is already known (e.g. chosen by the user from a picker).
|
|
124
|
+
*
|
|
125
|
+
* @param root project root
|
|
126
|
+
* @param filePath absolute path to the target `.properties` file
|
|
127
|
+
* @param newEntries translation entries to write
|
|
128
|
+
* @param fs optional `mem-fs-editor` instance
|
|
129
|
+
* @returns boolean or exception
|
|
130
|
+
*/
|
|
131
|
+
export async function createI18nEntriesAtPath(root, filePath, newEntries, fs) {
|
|
132
|
+
const dirPath = dirname(filePath);
|
|
133
|
+
if (!fs) {
|
|
134
|
+
await mkdir(dirPath, { recursive: true });
|
|
135
|
+
}
|
|
136
|
+
return createPropertiesI18nEntries(filePath, newEntries, root, fs);
|
|
137
|
+
}
|
|
121
138
|
/**
|
|
122
139
|
* Maintains new translation entries in an existing i18n file or in a new i18n properties file if it does not exist.
|
|
123
140
|
*
|
|
124
141
|
* @param root project root
|
|
125
|
-
* @param i18nPropertiesPaths paths to `.properties` file
|
|
142
|
+
* @param i18nPropertiesPaths paths to `.properties` file
|
|
126
143
|
* @param newEntries translation entries to write in the `.properties` file
|
|
127
144
|
* @param fs optional `mem-fs-editor` instance. If provided, `mem-fs-editor` api is used instead of `fs` of node
|
|
128
145
|
* @returns boolean or exception
|
package/dist/project/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export { clearCdsModuleCache, deleteCapApp, getCapCustomPaths, getCapEnvironment
|
|
|
2
2
|
export { filterDataSourcesByType, getMainService, getUsedEntitiesFromManifest } from './service.js';
|
|
3
3
|
export type { UsedEntity } from './service.js';
|
|
4
4
|
export { addPackageDevDependency, getNodeModulesPath, hasDependency } from './dependencies.js';
|
|
5
|
-
export { getCapI18nFolderNames, getI18nPropertiesPaths, getI18nBundles } from './i18n/index.js';
|
|
5
|
+
export { getCapI18nFolderNames, getI18nPropertiesPaths, getI18nBundles, createI18nEntriesAtPath } from './i18n/index.js';
|
|
6
6
|
export { getAppProgrammingLanguage, getAppType, getMinUI5VersionFromManifest, getMinUI5VersionAsArray, getMinimumUI5Version, getProject, getProjectType } from './info.js';
|
|
7
7
|
export { loadModuleFromProject } from './module-loader.js';
|
|
8
8
|
export { findAllApps, findCapProjects, findFioriArtifacts, findProjectRoot, getAppRootFromWebappPath, findCapProjectRoot, findRootsForPath } from './search.js';
|
package/dist/project/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { clearCdsModuleCache, deleteCapApp, getCapCustomPaths, getCapEnvironment, getCapModelAndServices, getCapProjectType, getCapServiceName, getCdsFiles, getCdsRoots, getCdsServices, isCapProject, isCapJavaProject, isCapNodeJsProject, readCapServiceMetadataEdmx, toReferenceUri, getWorkspaceInfo, hasMinCdsVersion, checkCdsUi5PluginEnabled, processServices, getGlobalCdsHomePath } from './cap.js';
|
|
2
2
|
export { filterDataSourcesByType, getMainService, getUsedEntitiesFromManifest } from './service.js';
|
|
3
3
|
export { addPackageDevDependency, getNodeModulesPath, hasDependency } from './dependencies.js';
|
|
4
|
-
export { getCapI18nFolderNames, getI18nPropertiesPaths, getI18nBundles } from './i18n/index.js';
|
|
4
|
+
export { getCapI18nFolderNames, getI18nPropertiesPaths, getI18nBundles, createI18nEntriesAtPath } from './i18n/index.js';
|
|
5
5
|
export { getAppProgrammingLanguage, getAppType, getMinUI5VersionFromManifest, getMinUI5VersionAsArray, getMinimumUI5Version, getProject, getProjectType } from './info.js';
|
|
6
6
|
export { loadModuleFromProject } from './module-loader.js';
|
|
7
7
|
export { findAllApps, findCapProjects, findFioriArtifacts, findProjectRoot, getAppRootFromWebappPath, findCapProjectRoot, findRootsForPath } from './search.js';
|
|
@@ -74,6 +74,15 @@ export interface ApplicationAccess extends BaseAccess {
|
|
|
74
74
|
* @returns boolean or exception
|
|
75
75
|
*/
|
|
76
76
|
createCapI18nEntries(filePath: string, newI18nEntries: NewI18nEntry[]): Promise<boolean>;
|
|
77
|
+
/**
|
|
78
|
+
* Maintains new translation entries at a specific i18n properties file path.
|
|
79
|
+
* Use this when the target file is already known (e.g. chosen by the user from a picker).
|
|
80
|
+
*
|
|
81
|
+
* @param filePath absolute path to the target `.properties` file
|
|
82
|
+
* @param newEntries translation entries to write
|
|
83
|
+
* @returns boolean or exception
|
|
84
|
+
*/
|
|
85
|
+
createI18nEntriesAtPath(filePath: string, newEntries: NewI18nEntry[]): Promise<boolean>;
|
|
77
86
|
/**
|
|
78
87
|
* Return the application id of this app, which is the relative path from the project root
|
|
79
88
|
* to the app root.
|
|
@@ -59,12 +59,22 @@ export interface I18nPropertiesPaths {
|
|
|
59
59
|
* Absolute path to the i18n.properties file from sap.app namespace.
|
|
60
60
|
*/
|
|
61
61
|
'sap.app': string;
|
|
62
|
+
/**
|
|
63
|
+
* Absolute path to the fallback locale i18n file from sap.app namespace, e.g. i18n_en.properties.
|
|
64
|
+
* Only set when `fallbackLocale` is configured in `sap.app.i18n`.
|
|
65
|
+
*/
|
|
66
|
+
'sap.app.fallbackLocale'?: string;
|
|
62
67
|
models: {
|
|
63
68
|
[modelKey: string]: {
|
|
64
69
|
/**
|
|
65
70
|
* Absolute path to the i18n.properties files.
|
|
66
71
|
*/
|
|
67
72
|
path: string;
|
|
73
|
+
/**
|
|
74
|
+
* Absolute path to the fallback locale i18n file, e.g. i18n_en.properties.
|
|
75
|
+
* Only set when `fallbackLocale` is configured in the model settings.
|
|
76
|
+
*/
|
|
77
|
+
fallbackLocalePath?: string;
|
|
68
78
|
};
|
|
69
79
|
};
|
|
70
80
|
}
|