@seshuk/payload-plugin-openapi 0.1.0 → 0.2.1
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/README.md +55 -539
- package/dist/index.d.ts +1 -1
- package/dist/options.js +1 -0
- package/dist/spec/buildDocument.js +39 -5
- package/dist/spec/components.d.ts +0 -2
- package/dist/spec/components.js +1 -16
- package/dist/spec/downconvert.d.ts +1 -1
- package/dist/spec/downconvert.js +27 -8
- package/dist/spec/entitySchemas.js +36 -32
- package/dist/spec/filters.js +12 -3
- package/dist/spec/params.d.ts +9 -1
- package/dist/spec/params.js +93 -1
- package/dist/spec/paths/auth.js +52 -63
- package/dist/spec/paths/collections.d.ts +3 -1
- package/dist/spec/paths/collections.js +42 -25
- package/dist/spec/paths/globals.d.ts +3 -1
- package/dist/spec/paths/globals.js +23 -13
- package/dist/spec/paths/versions.d.ts +2 -1
- package/dist/spec/paths/versions.js +14 -5
- package/dist/spec/security.d.ts +19 -0
- package/dist/spec/security.js +96 -0
- package/dist/translations/locales/ar.js +5 -0
- package/dist/translations/locales/az.js +5 -0
- package/dist/translations/locales/bg.js +5 -0
- package/dist/translations/locales/bnBd.js +5 -0
- package/dist/translations/locales/bnIn.js +5 -0
- package/dist/translations/locales/ca.js +5 -0
- package/dist/translations/locales/cs.js +5 -0
- package/dist/translations/locales/da.js +5 -0
- package/dist/translations/locales/de.js +5 -0
- package/dist/translations/locales/en.js +5 -0
- package/dist/translations/locales/es.js +5 -0
- package/dist/translations/locales/et.js +5 -0
- package/dist/translations/locales/fa.js +5 -0
- package/dist/translations/locales/fr.js +5 -0
- package/dist/translations/locales/he.js +5 -0
- package/dist/translations/locales/hr.js +5 -0
- package/dist/translations/locales/hu.js +5 -0
- package/dist/translations/locales/hy.js +5 -0
- package/dist/translations/locales/id.js +5 -0
- package/dist/translations/locales/is.js +5 -0
- package/dist/translations/locales/it.js +5 -0
- package/dist/translations/locales/ja.js +5 -0
- package/dist/translations/locales/ko.js +5 -0
- package/dist/translations/locales/lt.js +5 -0
- package/dist/translations/locales/lv.js +5 -0
- package/dist/translations/locales/my.js +5 -0
- package/dist/translations/locales/nb.js +5 -0
- package/dist/translations/locales/nl.js +5 -0
- package/dist/translations/locales/pl.js +5 -0
- package/dist/translations/locales/pt.js +5 -0
- package/dist/translations/locales/ro.js +5 -0
- package/dist/translations/locales/rs.js +5 -0
- package/dist/translations/locales/rsLatin.js +5 -0
- package/dist/translations/locales/ru.js +5 -0
- package/dist/translations/locales/sk.js +5 -0
- package/dist/translations/locales/sl.js +5 -0
- package/dist/translations/locales/sv.js +5 -0
- package/dist/translations/locales/ta.js +5 -0
- package/dist/translations/locales/th.js +5 -0
- package/dist/translations/locales/tr.js +5 -0
- package/dist/translations/locales/uk.js +5 -0
- package/dist/translations/locales/vi.js +5 -0
- package/dist/translations/locales/zh.js +5 -0
- package/dist/translations/locales/zhTw.js +5 -0
- package/dist/translations/types.d.ts +5 -0
- package/dist/types.d.ts +9 -0
- package/package.json +39 -24
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { makeT } from "../../translations/index.js";
|
|
2
|
-
import { ERRORS,
|
|
2
|
+
import { ERRORS, errorResponses, jsonOk, jsonResponse, uploadRequestBody } from "../components.js";
|
|
3
3
|
import { createSchemaName, listSchemaName, refTo, schemaName, updateSchemaName } from "../names.js";
|
|
4
|
-
import { buildListParams, buildParamSchemas, commonReadParams } from "../params.js";
|
|
5
|
-
const buildCollectionPaths = ({ collection, ctx })=>{
|
|
4
|
+
import { buildListParams, buildParamSchemas, commonReadParams, writeParams } from "../params.js";
|
|
5
|
+
const buildCollectionPaths = ({ collection, ctx, security = {} })=>{
|
|
6
6
|
const t = makeT(ctx.i18n);
|
|
7
7
|
const name = schemaName(collection.slug);
|
|
8
8
|
const base = `${ctx.apiRoute}/${collection.slug}`;
|
|
@@ -19,11 +19,7 @@ const buildCollectionPaths = ({ collection, ctx })=>{
|
|
|
19
19
|
$ref: refTo(updateSchemaName(name))
|
|
20
20
|
};
|
|
21
21
|
const idType = 'number' === ctx.defaultIDType ? 'integer' : 'string';
|
|
22
|
-
const
|
|
23
|
-
{
|
|
24
|
-
[SECURITY_SCHEME_NAME]: []
|
|
25
|
-
}
|
|
26
|
-
];
|
|
22
|
+
const { read: secRead, create: secCreate, update: secUpdate, delete: secDelete } = security;
|
|
27
23
|
const allowBulk = true !== collection.disableBulkEdit;
|
|
28
24
|
const allowDuplicate = true !== collection.disableDuplicate;
|
|
29
25
|
const paramSchemas = buildParamSchemas({
|
|
@@ -66,7 +62,7 @@ const buildCollectionPaths = ({ collection, ctx })=>{
|
|
|
66
62
|
...errorResponses(ERRORS.read, t)
|
|
67
63
|
};
|
|
68
64
|
const createResponse = {
|
|
69
|
-
|
|
65
|
+
201: jsonResponse(t('collectionCreated'), mutationSchema),
|
|
70
66
|
...errorResponses(ERRORS.create, t)
|
|
71
67
|
};
|
|
72
68
|
const updateResponse = {
|
|
@@ -122,34 +118,51 @@ const buildCollectionPaths = ({ collection, ctx })=>{
|
|
|
122
118
|
}),
|
|
123
119
|
...errorResponses(ERRORS.list, t)
|
|
124
120
|
};
|
|
125
|
-
const
|
|
121
|
+
const listParams = buildListParams({
|
|
126
122
|
base: name,
|
|
127
123
|
fields: collection.fields,
|
|
128
124
|
ctx,
|
|
129
125
|
refs
|
|
130
|
-
})
|
|
131
|
-
const bulkParams =
|
|
132
|
-
|
|
133
|
-
|
|
126
|
+
});
|
|
127
|
+
const bulkParams = listParams.filter((p)=>'where' === p.name);
|
|
128
|
+
const bulkUpdateParams = listParams.filter((p)=>[
|
|
129
|
+
'limit',
|
|
130
|
+
'sort',
|
|
131
|
+
'where'
|
|
132
|
+
].includes(p.name));
|
|
133
|
+
const write = (operation)=>writeParams({
|
|
134
|
+
base: name,
|
|
135
|
+
entity: collection,
|
|
136
|
+
ctx,
|
|
137
|
+
refs,
|
|
138
|
+
operation
|
|
139
|
+
});
|
|
140
|
+
const deleteParams = write('delete');
|
|
134
141
|
const bulkOps = allowBulk ? {
|
|
135
142
|
patch: {
|
|
136
143
|
tags: [
|
|
137
144
|
name
|
|
138
145
|
],
|
|
139
146
|
operationId: `update${name}`,
|
|
140
|
-
parameters:
|
|
147
|
+
parameters: [
|
|
148
|
+
...bulkUpdateParams,
|
|
149
|
+
...write('update')
|
|
150
|
+
],
|
|
141
151
|
requestBody: requestBody(updateRef, false),
|
|
142
152
|
responses: bulkUpdateResponse,
|
|
143
|
-
security:
|
|
153
|
+
security: secUpdate
|
|
144
154
|
},
|
|
145
155
|
delete: {
|
|
146
156
|
tags: [
|
|
147
157
|
name
|
|
148
158
|
],
|
|
149
159
|
operationId: `delete${name}`,
|
|
150
|
-
parameters:
|
|
160
|
+
parameters: [
|
|
161
|
+
...bulkParams,
|
|
162
|
+
...deleteParams
|
|
163
|
+
],
|
|
151
164
|
responses: bulkDeleteResponse,
|
|
152
|
-
security:
|
|
165
|
+
security: secDelete
|
|
153
166
|
}
|
|
154
167
|
} : {};
|
|
155
168
|
const paths = {
|
|
@@ -166,16 +179,17 @@ const buildCollectionPaths = ({ collection, ctx })=>{
|
|
|
166
179
|
refs
|
|
167
180
|
}),
|
|
168
181
|
responses: listResponse,
|
|
169
|
-
security:
|
|
182
|
+
security: secRead
|
|
170
183
|
},
|
|
171
184
|
post: {
|
|
172
185
|
tags: [
|
|
173
186
|
name
|
|
174
187
|
],
|
|
175
188
|
operationId: `create${name}`,
|
|
189
|
+
parameters: write('create'),
|
|
176
190
|
requestBody: requestBody(createRef, fileRequiredOnCreate),
|
|
177
191
|
responses: createResponse,
|
|
178
|
-
security:
|
|
192
|
+
security: secCreate
|
|
179
193
|
},
|
|
180
194
|
...bulkOps
|
|
181
195
|
},
|
|
@@ -187,7 +201,7 @@ const buildCollectionPaths = ({ collection, ctx })=>{
|
|
|
187
201
|
operationId: `count${name}`,
|
|
188
202
|
parameters: bulkParams,
|
|
189
203
|
responses: countResponse,
|
|
190
|
-
security:
|
|
204
|
+
security: secRead
|
|
191
205
|
}
|
|
192
206
|
},
|
|
193
207
|
[`${base}/{id}`]: {
|
|
@@ -212,24 +226,26 @@ const buildCollectionPaths = ({ collection, ctx })=>{
|
|
|
212
226
|
refs
|
|
213
227
|
}),
|
|
214
228
|
responses: findByIdResponse,
|
|
215
|
-
security:
|
|
229
|
+
security: secRead
|
|
216
230
|
},
|
|
217
231
|
patch: {
|
|
218
232
|
tags: [
|
|
219
233
|
name
|
|
220
234
|
],
|
|
221
235
|
operationId: `update${name}ById`,
|
|
236
|
+
parameters: write('updateByID'),
|
|
222
237
|
requestBody: requestBody(updateRef, false),
|
|
223
238
|
responses: updateResponse,
|
|
224
|
-
security:
|
|
239
|
+
security: secUpdate
|
|
225
240
|
},
|
|
226
241
|
delete: {
|
|
227
242
|
tags: [
|
|
228
243
|
name
|
|
229
244
|
],
|
|
230
245
|
operationId: `delete${name}ById`,
|
|
246
|
+
parameters: deleteParams,
|
|
231
247
|
responses: deleteResponse,
|
|
232
|
-
security:
|
|
248
|
+
security: secDelete
|
|
233
249
|
}
|
|
234
250
|
}
|
|
235
251
|
};
|
|
@@ -249,11 +265,12 @@ const buildCollectionPaths = ({ collection, ctx })=>{
|
|
|
249
265
|
name
|
|
250
266
|
],
|
|
251
267
|
operationId: `duplicate${name}`,
|
|
268
|
+
parameters: write('duplicate'),
|
|
252
269
|
responses: {
|
|
253
270
|
...jsonOk(t('collectionDuplicated'), mutationSchema),
|
|
254
271
|
...errorResponses(ERRORS.create, t)
|
|
255
272
|
},
|
|
256
|
-
security:
|
|
273
|
+
security: secCreate
|
|
257
274
|
}
|
|
258
275
|
};
|
|
259
276
|
return paths;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { SanitizedGlobalConfig } from 'payload';
|
|
2
2
|
import type { PathsObject } from '@scalar/openapi-types/3.2';
|
|
3
3
|
import type { BuildContext } from '../../types.js';
|
|
4
|
-
|
|
4
|
+
import type { EntitySecurity } from '../security.js';
|
|
5
|
+
export declare const buildGlobalPaths: ({ global, ctx, security, }: {
|
|
5
6
|
global: SanitizedGlobalConfig;
|
|
6
7
|
ctx: BuildContext;
|
|
8
|
+
security?: EntitySecurity;
|
|
7
9
|
}) => PathsObject;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { makeT } from "../../translations/index.js";
|
|
2
|
-
import { ERRORS,
|
|
2
|
+
import { ERRORS, errorResponses, jsonOk } from "../components.js";
|
|
3
3
|
import { globalSchemaName, refTo, updateSchemaName } from "../names.js";
|
|
4
|
-
import { buildParamSchemas, commonReadParams } from "../params.js";
|
|
5
|
-
const buildGlobalPaths = ({ global, ctx })=>{
|
|
4
|
+
import { buildParamSchemas, commonReadParams, writeParams } from "../params.js";
|
|
5
|
+
const buildGlobalPaths = ({ global, ctx, security = {} })=>{
|
|
6
6
|
const t = makeT(ctx.i18n);
|
|
7
7
|
const name = globalSchemaName(global.slug);
|
|
8
8
|
const docRef = {
|
|
@@ -11,11 +11,7 @@ const buildGlobalPaths = ({ global, ctx })=>{
|
|
|
11
11
|
const updateRef = {
|
|
12
12
|
$ref: refTo(updateSchemaName(name))
|
|
13
13
|
};
|
|
14
|
-
const
|
|
15
|
-
{
|
|
16
|
-
[SECURITY_SCHEME_NAME]: []
|
|
17
|
-
}
|
|
18
|
-
];
|
|
14
|
+
const { read: secRead, update: secUpdate } = security;
|
|
19
15
|
const paramSchemas = buildParamSchemas({
|
|
20
16
|
fields: global.fields,
|
|
21
17
|
ctx
|
|
@@ -25,7 +21,6 @@ const buildGlobalPaths = ({ global, ctx })=>{
|
|
|
25
21
|
populate: Boolean(paramSchemas.populate),
|
|
26
22
|
joins: Boolean(paramSchemas.joins)
|
|
27
23
|
};
|
|
28
|
-
const okDoc = jsonOk(t('globalDoc'), docRef);
|
|
29
24
|
return {
|
|
30
25
|
[`${ctx.apiRoute}/globals/${global.slug}`]: {
|
|
31
26
|
get: {
|
|
@@ -39,16 +34,23 @@ const buildGlobalPaths = ({ global, ctx })=>{
|
|
|
39
34
|
refs
|
|
40
35
|
}),
|
|
41
36
|
responses: {
|
|
42
|
-
...
|
|
37
|
+
...jsonOk(t('globalDoc'), docRef),
|
|
43
38
|
...errorResponses(ERRORS.globalRead, t)
|
|
44
39
|
},
|
|
45
|
-
security:
|
|
40
|
+
security: secRead
|
|
46
41
|
},
|
|
47
42
|
post: {
|
|
48
43
|
tags: [
|
|
49
44
|
name
|
|
50
45
|
],
|
|
51
46
|
operationId: `update${name}`,
|
|
47
|
+
parameters: writeParams({
|
|
48
|
+
base: name,
|
|
49
|
+
entity: global,
|
|
50
|
+
ctx,
|
|
51
|
+
refs,
|
|
52
|
+
operation: 'globalUpdate'
|
|
53
|
+
}),
|
|
52
54
|
requestBody: {
|
|
53
55
|
content: {
|
|
54
56
|
'application/json': {
|
|
@@ -57,10 +59,18 @@ const buildGlobalPaths = ({ global, ctx })=>{
|
|
|
57
59
|
}
|
|
58
60
|
},
|
|
59
61
|
responses: {
|
|
60
|
-
...
|
|
62
|
+
...jsonOk(t('globalDoc'), {
|
|
63
|
+
type: 'object',
|
|
64
|
+
properties: {
|
|
65
|
+
message: {
|
|
66
|
+
type: 'string'
|
|
67
|
+
},
|
|
68
|
+
result: docRef
|
|
69
|
+
}
|
|
70
|
+
}),
|
|
61
71
|
...errorResponses(ERRORS.globalUpdate, t)
|
|
62
72
|
},
|
|
63
|
-
security:
|
|
73
|
+
security: secUpdate
|
|
64
74
|
}
|
|
65
75
|
}
|
|
66
76
|
};
|
|
@@ -9,10 +9,11 @@ export declare const versionComponentSchemas: ({ docBase, base, idType, }: {
|
|
|
9
9
|
base: string;
|
|
10
10
|
idType: IDType;
|
|
11
11
|
}) => VersionSchemas;
|
|
12
|
-
export declare const buildVersionPaths: ({ entity, pathBase, ctx, schemaBase, nestedTags, }: {
|
|
12
|
+
export declare const buildVersionPaths: ({ entity, pathBase, ctx, schemaBase, nestedTags, global, }: {
|
|
13
13
|
entity: Entity;
|
|
14
14
|
pathBase: string;
|
|
15
15
|
ctx: BuildContext;
|
|
16
16
|
schemaBase?: string;
|
|
17
17
|
nestedTags: boolean;
|
|
18
|
+
global?: boolean;
|
|
18
19
|
}) => PathsObject;
|
|
@@ -141,7 +141,7 @@ const listVersionParams = ({ base, ctx, refs })=>{
|
|
|
141
141
|
}
|
|
142
142
|
];
|
|
143
143
|
};
|
|
144
|
-
const buildVersionPaths = ({ entity, pathBase, ctx, schemaBase, nestedTags })=>{
|
|
144
|
+
const buildVersionPaths = ({ entity, pathBase, ctx, schemaBase, nestedTags, global = false })=>{
|
|
145
145
|
if (!entity.versions) return {};
|
|
146
146
|
const t = makeT(ctx.i18n);
|
|
147
147
|
const name = schemaBase ?? schemaName(entity.slug);
|
|
@@ -165,7 +165,18 @@ const buildVersionPaths = ({ entity, pathBase, ctx, schemaBase, nestedTags })=>{
|
|
|
165
165
|
type: 'number' === ctx.defaultIDType ? 'integer' : 'string'
|
|
166
166
|
}
|
|
167
167
|
};
|
|
168
|
-
const
|
|
168
|
+
const message = {
|
|
169
|
+
type: 'string'
|
|
170
|
+
};
|
|
171
|
+
const restoreResponse = global ? {
|
|
172
|
+
type: 'object',
|
|
173
|
+
properties: {
|
|
174
|
+
message,
|
|
175
|
+
doc: {
|
|
176
|
+
$ref: refTo(name)
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
} : {
|
|
169
180
|
allOf: [
|
|
170
181
|
{
|
|
171
182
|
$ref: refTo(name)
|
|
@@ -173,9 +184,7 @@ const buildVersionPaths = ({ entity, pathBase, ctx, schemaBase, nestedTags })=>{
|
|
|
173
184
|
{
|
|
174
185
|
type: 'object',
|
|
175
186
|
properties: {
|
|
176
|
-
message
|
|
177
|
-
type: 'string'
|
|
178
|
-
}
|
|
187
|
+
message
|
|
179
188
|
}
|
|
180
189
|
}
|
|
181
190
|
]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Access } from 'payload';
|
|
2
|
+
import type { PathsObject, SecurityRequirementObject } from '@scalar/openapi-types/3.2';
|
|
3
|
+
import type { Entity, EntityKind, EntityOperation, OperationContext } from '../types.js';
|
|
4
|
+
export type EntitySecurity = Partial<Record<EntityOperation, SecurityRequirementObject[] | undefined>>;
|
|
5
|
+
export declare const evaluateAccess: (access: Access | undefined, opts?: {
|
|
6
|
+
locale?: string;
|
|
7
|
+
timeoutMs?: number;
|
|
8
|
+
}) => Promise<boolean>;
|
|
9
|
+
export declare const resolveEntitySecurity: ({ entity, operations, locale, }: {
|
|
10
|
+
entity: Entity;
|
|
11
|
+
operations: EntityOperation[];
|
|
12
|
+
locale?: string;
|
|
13
|
+
}) => Promise<EntitySecurity>;
|
|
14
|
+
export declare const applySecurityWhen: ({ paths, slug, kind, securityWhen, }: {
|
|
15
|
+
paths: PathsObject;
|
|
16
|
+
slug: string;
|
|
17
|
+
kind: EntityKind;
|
|
18
|
+
securityWhen?: (ctx: OperationContext) => boolean | undefined;
|
|
19
|
+
}) => PathsObject;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { SECURITY_SCHEME_NAME } from "./components.js";
|
|
2
|
+
const HTTP_METHODS = [
|
|
3
|
+
'get',
|
|
4
|
+
'post',
|
|
5
|
+
'patch',
|
|
6
|
+
'put',
|
|
7
|
+
'delete'
|
|
8
|
+
];
|
|
9
|
+
const securedRequirement = ()=>[
|
|
10
|
+
{
|
|
11
|
+
[SECURITY_SCHEME_NAME]: []
|
|
12
|
+
}
|
|
13
|
+
];
|
|
14
|
+
const withTimeout = async (promise, timeoutMs)=>{
|
|
15
|
+
let timer;
|
|
16
|
+
const guard = new Promise((resolve)=>{
|
|
17
|
+
timer = setTimeout(()=>resolve(false), timeoutMs);
|
|
18
|
+
});
|
|
19
|
+
try {
|
|
20
|
+
return await Promise.race([
|
|
21
|
+
promise.then((value)=>true === value, ()=>false),
|
|
22
|
+
guard
|
|
23
|
+
]);
|
|
24
|
+
} finally{
|
|
25
|
+
if (timer) clearTimeout(timer);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
const evaluateAccess = async (access, opts = {})=>{
|
|
29
|
+
if (!access) return false;
|
|
30
|
+
const { locale, timeoutMs = 250 } = opts;
|
|
31
|
+
const payloadTrap = new Proxy({}, {
|
|
32
|
+
get () {
|
|
33
|
+
throw new Error('req.payload accessed during build');
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
const req = {
|
|
37
|
+
user: null,
|
|
38
|
+
headers: new Headers(),
|
|
39
|
+
context: {},
|
|
40
|
+
locale,
|
|
41
|
+
payload: payloadTrap
|
|
42
|
+
};
|
|
43
|
+
try {
|
|
44
|
+
const result = access({
|
|
45
|
+
req
|
|
46
|
+
});
|
|
47
|
+
if (result && 'function' == typeof result.then) return await withTimeout(result, timeoutMs);
|
|
48
|
+
return true === result;
|
|
49
|
+
} catch {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
const readSecurityOverride = (entity)=>{
|
|
54
|
+
const meta = entity.custom?.openapi?.security;
|
|
55
|
+
if ('boolean' == typeof meta) return meta;
|
|
56
|
+
if (meta && 'object' == typeof meta) return meta;
|
|
57
|
+
};
|
|
58
|
+
const overrideFor = (override, op)=>{
|
|
59
|
+
if (void 0 === override) return;
|
|
60
|
+
if ('boolean' == typeof override) return override;
|
|
61
|
+
return override[op];
|
|
62
|
+
};
|
|
63
|
+
const resolveEntitySecurity = async ({ entity, operations, locale })=>{
|
|
64
|
+
const override = readSecurityOverride(entity);
|
|
65
|
+
const access = entity.access;
|
|
66
|
+
const out = {};
|
|
67
|
+
for (const op of operations){
|
|
68
|
+
const declared = overrideFor(override, op);
|
|
69
|
+
const isPublic = declared ?? await evaluateAccess(access?.[op], {
|
|
70
|
+
locale
|
|
71
|
+
});
|
|
72
|
+
out[op] = isPublic ? void 0 : securedRequirement();
|
|
73
|
+
}
|
|
74
|
+
return out;
|
|
75
|
+
};
|
|
76
|
+
const applySecurityWhen = ({ paths, slug, kind, securityWhen })=>{
|
|
77
|
+
if (!securityWhen) return paths;
|
|
78
|
+
for (const [path, item] of Object.entries(paths)){
|
|
79
|
+
if (!item) continue;
|
|
80
|
+
const ops = item;
|
|
81
|
+
for (const method of HTTP_METHODS){
|
|
82
|
+
const op = ops[method];
|
|
83
|
+
if (!op) continue;
|
|
84
|
+
const decision = securityWhen({
|
|
85
|
+
method,
|
|
86
|
+
path,
|
|
87
|
+
slug,
|
|
88
|
+
kind
|
|
89
|
+
});
|
|
90
|
+
if (true === decision) delete op.security;
|
|
91
|
+
else if (false === decision) op.security = securedRequirement();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return paths;
|
|
95
|
+
};
|
|
96
|
+
export { applySecurityWhen, evaluateAccess, resolveEntitySecurity };
|
|
@@ -5,6 +5,11 @@ const ar = {
|
|
|
5
5
|
paramSortShort: 'الحقل المراد الترتيب حسبه؛ ضع البادئة `-` للترتيب التنازلي.',
|
|
6
6
|
paramDraft: 'إرجاع نسخ المسودة.',
|
|
7
7
|
paramTrash: 'تضمين المستندات المحذوفة.',
|
|
8
|
+
paramAutosave: 'الحفظ كحفظ تلقائي: تحديث آخر نسخة محفوظة تلقائيًا بدلًا من إضافة نسخة جديدة.',
|
|
9
|
+
paramPublishAllLocales: 'نشر كل اللغات، وليس لغة الطلب فقط.',
|
|
10
|
+
paramUnpublishAllLocales: 'إلغاء نشر كل اللغات وإعادة المستند إلى مسودة.',
|
|
11
|
+
paramOverrideLock: 'تجاهل القفل الذي يملكه مستخدم آخر. الافتراضي false.',
|
|
12
|
+
paramSelectedLocales: 'نسخ هذه اللغات فقط إلى النسخة المكررة. الافتراضي: كل اللغات.',
|
|
8
13
|
paramFlattenLocales: 'مع `locale=all`، اضبط على false للإبقاء على الحقول المترجمة ككائنات لكل لغة. القيمة الافتراضية true.',
|
|
9
14
|
paramLocale: 'اللغة المراد إرجاعها، أو `all` لكل اللغات. راجع قسم الترجمة في وصف الـ API.',
|
|
10
15
|
paramFallbackLocale: 'اللغة الاحتياطية للقيم المترجمة المفقودة، أو `none` للتعطيل.',
|
|
@@ -5,6 +5,11 @@ const az = {
|
|
|
5
5
|
paramSortShort: 'Sıralanacaq sahə; azalan sıra üçün önünə `-` əlavə edin.',
|
|
6
6
|
paramDraft: 'Qaralama versiyalarını qaytarın.',
|
|
7
7
|
paramTrash: 'Zibilə atılmış sənədləri daxil edin.',
|
|
8
|
+
paramAutosave: 'Avtomatik yadda saxlama kimi saxlayın: yeni versiya əlavə etmək əvəzinə son avtomatik versiyanı yeniləyin.',
|
|
9
|
+
paramPublishAllLocales: 'Yalnız sorğu dilini deyil, bütün dilləri dərc edin.',
|
|
10
|
+
paramUnpublishAllLocales: 'Bütün dillərin dərcini ləğv edin və sənədi qaralamaya qaytarın.',
|
|
11
|
+
paramOverrideLock: 'Başqa istifadəçinin kilidinə məhəl qoymayın. Defolt false.',
|
|
12
|
+
paramSelectedLocales: 'Dublikata yalnız bu dilləri köçürün. Defolt: bütün dillər.',
|
|
8
13
|
paramFlattenLocales: '`locale=all` ilə, lokallaşdırılmış sahələri hər lokal üzrə obyekt kimi saxlamaq üçün false təyin edin. Standart olaraq true.',
|
|
9
14
|
paramLocale: 'Qaytarılacaq lokal, və ya hər lokal üçün `all`. API təsvirindəki Lokallaşdırma bölməsinə baxın.',
|
|
10
15
|
paramFallbackLocale: 'Çatışmayan lokallaşdırılmış dəyərlər üçün geri dönüləcək lokal, və ya söndürmək üçün `none`.',
|
|
@@ -5,6 +5,11 @@ const bg = {
|
|
|
5
5
|
paramSortShort: 'Поле за сортиране; добавете префикс `-` за низходящ ред.',
|
|
6
6
|
paramDraft: 'Връщане на чернови версии.',
|
|
7
7
|
paramTrash: 'Включване на документите в кошчето.',
|
|
8
|
+
paramAutosave: 'Запис като автоматично запазване: обновява последната автоматична версия, вместо да добавя нова.',
|
|
9
|
+
paramPublishAllLocales: 'Публикуване на всички езици, не само на езика на заявката.',
|
|
10
|
+
paramUnpublishAllLocales: 'Отмяна на публикуването на всички езици и връщане на документа в чернова.',
|
|
11
|
+
paramOverrideLock: 'Игнориране на заключване от друг потребител. По подразбиране false.',
|
|
12
|
+
paramSelectedLocales: 'Копиране само на тези езици в дубликата. По подразбиране: всички езици.',
|
|
8
13
|
paramFlattenLocales: 'С `locale=all` задайте false, за да запазите локализираните полета като обекти по локал. По подразбиране true.',
|
|
9
14
|
paramLocale: 'Локал за връщане или `all` за всеки локал. Вижте раздела Localization в описанието на API.',
|
|
10
15
|
paramFallbackLocale: 'Локал, към който да се връща при липсващи локализирани стойности, или `none` за изключване.',
|
|
@@ -5,6 +5,11 @@ const bnBd = {
|
|
|
5
5
|
paramSortShort: 'যে ফিল্ড দিয়ে সাজানো হবে; অবরোহী ক্রমের জন্য `-` উপসর্গ দিন।',
|
|
6
6
|
paramDraft: 'ড্রাফট সংস্করণ ফেরত দিন।',
|
|
7
7
|
paramTrash: 'ট্র্যাশে থাকা ডকুমেন্ট অন্তর্ভুক্ত করুন।',
|
|
8
|
+
paramAutosave: 'অটোসেভ হিসেবে সংরক্ষণ করুন: নতুন সংস্করণ যোগ না করে সর্বশেষ অটোসেভ সংস্করণ হালনাগাদ করুন।',
|
|
9
|
+
paramPublishAllLocales: 'শুধু অনুরোধের ভাষা নয়, সব ভাষা প্রকাশ করুন।',
|
|
10
|
+
paramUnpublishAllLocales: 'সব ভাষার প্রকাশ বাতিল করে ডকুমেন্টকে আবার ড্রাফট করুন।',
|
|
11
|
+
paramOverrideLock: 'অন্য ব্যবহারকারীর লক উপেক্ষা করুন। ডিফল্ট false।',
|
|
12
|
+
paramSelectedLocales: 'ডুপ্লিকেটে শুধু এই ভাষাগুলো কপি করুন। ডিফল্ট: সব ভাষা।',
|
|
8
13
|
paramFlattenLocales: '`locale=all` এর সাথে, লোকালাইজড ফিল্ডগুলো প্রতি-লোকেল অবজেক্ট হিসেবে রাখতে false সেট করুন। ডিফল্ট true।',
|
|
9
14
|
paramLocale: 'যে লোকেল ফেরত দিতে হবে, অথবা প্রতিটি লোকেলের জন্য `all`। API বিবরণের Localization অংশটি দেখুন।',
|
|
10
15
|
paramFallbackLocale: 'অনুপস্থিত লোকালাইজড মানের জন্য যে লোকেলে ফিরে যাওয়া হবে, অথবা নিষ্ক্রিয় করতে `none`।',
|
|
@@ -5,6 +5,11 @@ const bnIn = {
|
|
|
5
5
|
paramSortShort: 'যে ফিল্ড অনুযায়ী সাজানো হবে; অবরোহী ক্রমের জন্য `-` দিয়ে শুরু করুন।',
|
|
6
6
|
paramDraft: 'খসড়া সংস্করণ ফেরত দিন।',
|
|
7
7
|
paramTrash: 'আবর্জনায় থাকা নথি অন্তর্ভুক্ত করুন।',
|
|
8
|
+
paramAutosave: 'অটোসেভ হিসেবে সংরক্ষণ করুন: নতুন সংস্করণ যোগ না করে সর্বশেষ অটোসেভ সংস্করণ আপডেট করুন।',
|
|
9
|
+
paramPublishAllLocales: 'শুধু অনুরোধের ভাষা নয়, সব ভাষা প্রকাশ করুন।',
|
|
10
|
+
paramUnpublishAllLocales: 'সব ভাষার প্রকাশ বাতিল করে নথিটিকে আবার খসড়া করুন।',
|
|
11
|
+
paramOverrideLock: 'অন্য ব্যবহারকারীর লক উপেক্ষা করুন। ডিফল্ট false।',
|
|
12
|
+
paramSelectedLocales: 'প্রতিলিপিতে শুধু এই ভাষাগুলি কপি করুন। ডিফল্ট: সব ভাষা।',
|
|
8
13
|
paramFlattenLocales: '`locale=all` সহ, স্থানীয়কৃত ফিল্ডগুলো প্রতি-লোকেল অবজেক্ট হিসেবে রাখতে false সেট করুন। ডিফল্ট true।',
|
|
9
14
|
paramLocale: 'যে লোকেল ফেরত দেওয়া হবে, অথবা প্রতিটি লোকেলের জন্য `all`। API বিবরণে Localization বিভাগটি দেখুন।',
|
|
10
15
|
paramFallbackLocale: 'অনুপস্থিত স্থানীয়কৃত মানের জন্য যে লোকেলে ফিরে যাওয়া হবে, অথবা নিষ্ক্রিয় করতে `none`।',
|
|
@@ -5,6 +5,11 @@ const ca = {
|
|
|
5
5
|
paramSortShort: 'Camp pel qual ordenar; afegiu el prefix `-` per a ordre descendent.',
|
|
6
6
|
paramDraft: "Retorna les versions d'esborrany.",
|
|
7
7
|
paramTrash: 'Inclou els documents enviats a la paperera.',
|
|
8
|
+
paramAutosave: "Desa com a desat automàtic: actualitza l'última versió desada automàticament en lloc d'afegir-ne una de nova.",
|
|
9
|
+
paramPublishAllLocales: 'Publica tots els idiomes, no només el de la petició.',
|
|
10
|
+
paramUnpublishAllLocales: 'Despublica tots els idiomes i torna el document a esborrany.',
|
|
11
|
+
paramOverrideLock: "Ignora un bloqueig d'un altre usuari. Per defecte false.",
|
|
12
|
+
paramSelectedLocales: 'Copia només aquests idiomes al duplicat. Per defecte: tots els idiomes.',
|
|
8
13
|
paramFlattenLocales: 'Amb `locale=all`, establiu-ho a false per mantenir els camps localitzats com a objectes per localització. Per defecte és true.',
|
|
9
14
|
paramLocale: "Localització a retornar, o `all` per a totes les localitzacions. Vegeu la secció Localització a la descripció de l'API.",
|
|
10
15
|
paramFallbackLocale: 'Localització de reserva per als valors localitzats que manquin, o `none` per desactivar-la.',
|
|
@@ -5,6 +5,11 @@ const cs = {
|
|
|
5
5
|
paramSortShort: 'Pole pro řazení; pro sestupné řazení použijte předponu `-`.',
|
|
6
6
|
paramDraft: 'Vrátit koncepty (draft verze).',
|
|
7
7
|
paramTrash: 'Zahrnout dokumenty v koši.',
|
|
8
|
+
paramAutosave: 'Uložit jako automatické uložení: aktualizuje poslední automaticky uloženou verzi místo přidání nové.',
|
|
9
|
+
paramPublishAllLocales: 'Publikovat všechny jazyky, nejen jazyk požadavku.',
|
|
10
|
+
paramUnpublishAllLocales: 'Zrušit publikování všech jazyků a vrátit dokument do konceptu.',
|
|
11
|
+
paramOverrideLock: 'Ignorovat zámek jiného uživatele. Výchozí false.',
|
|
12
|
+
paramSelectedLocales: 'Zkopírovat do duplikátu jen tyto jazyky. Výchozí: všechny jazyky.',
|
|
8
13
|
paramFlattenLocales: 'S `locale=all` nastavte false, aby lokalizovaná pole zůstala jako objekty po jednotlivých jazycích. Výchozí hodnota je true.',
|
|
9
14
|
paramLocale: 'Jazyk, který se má vrátit, nebo `all` pro všechny jazyky. Viz sekce Lokalizace v popisu API.',
|
|
10
15
|
paramFallbackLocale: 'Jazyk, na který se přejde u chybějících lokalizovaných hodnot, nebo `none` pro vypnutí.',
|
|
@@ -5,6 +5,11 @@ const da = {
|
|
|
5
5
|
paramSortShort: 'Felt at sortere efter; sæt `-` foran for faldende rækkefølge.',
|
|
6
6
|
paramDraft: 'Returnér kladdeversioner.',
|
|
7
7
|
paramTrash: 'Inkludér slettede dokumenter.',
|
|
8
|
+
paramAutosave: 'Gem som autogem: opdaterer den seneste autogemte version i stedet for at tilføje en ny.',
|
|
9
|
+
paramPublishAllLocales: 'Udgiv alle sprog, ikke kun forespørgslens sprog.',
|
|
10
|
+
paramUnpublishAllLocales: 'Afpublicér alle sprog og sæt dokumentet tilbage til kladde.',
|
|
11
|
+
paramOverrideLock: 'Ignorér en lås fra en anden bruger. Standard false.',
|
|
12
|
+
paramSelectedLocales: 'Kopiér kun disse sprog til dubletten. Standard: alle sprog.',
|
|
8
13
|
paramFlattenLocales: 'Med `locale=all` skal du sætte false for at bevare lokaliserede felter som objekter pr. sprog. Standard er true.',
|
|
9
14
|
paramLocale: 'Sprog der skal returneres, eller `all` for alle sprog. Se afsnittet Lokalisering i API-beskrivelsen.',
|
|
10
15
|
paramFallbackLocale: 'Sprog der skal falde tilbage til for manglende lokaliserede værdier, eller `none` for at deaktivere.',
|
|
@@ -5,6 +5,11 @@ const de = {
|
|
|
5
5
|
paramSortShort: 'Feld, nach dem sortiert wird; für absteigende Sortierung mit `-` voranstellen.',
|
|
6
6
|
paramDraft: 'Entwurfsversionen zurückgeben.',
|
|
7
7
|
paramTrash: 'Gelöschte Dokumente einbeziehen.',
|
|
8
|
+
paramAutosave: 'Als Autosave speichern: aktualisiert die letzte Autosave-Version, statt eine neue anzulegen.',
|
|
9
|
+
paramPublishAllLocales: 'Alle Sprachen veröffentlichen, nicht nur die Sprache der Anfrage.',
|
|
10
|
+
paramUnpublishAllLocales: 'Die Veröffentlichung aller Sprachen aufheben und das Dokument wieder zum Entwurf machen.',
|
|
11
|
+
paramOverrideLock: 'Eine Sperre eines anderen Benutzers ignorieren. Standard false.',
|
|
12
|
+
paramSelectedLocales: 'Nur diese Sprachen in das Duplikat kopieren. Standard: alle Sprachen.',
|
|
8
13
|
paramFlattenLocales: 'Mit `locale=all` auf false setzen, um lokalisierte Felder als Objekte je Sprache zu behalten. Standard ist true.',
|
|
9
14
|
paramLocale: 'Zurückzugebende Sprache oder `all` für alle Sprachen. Siehe den Abschnitt zur Lokalisierung in der API-Beschreibung.',
|
|
10
15
|
paramFallbackLocale: 'Sprache, auf die bei fehlenden lokalisierten Werten zurückgegriffen wird, oder `none` zum Deaktivieren.',
|
|
@@ -5,6 +5,11 @@ const en = {
|
|
|
5
5
|
paramSortShort: 'Field to sort by; prefix with `-` for descending.',
|
|
6
6
|
paramDraft: 'Return draft versions.',
|
|
7
7
|
paramTrash: 'Include trashed documents.',
|
|
8
|
+
paramAutosave: 'Save as an autosave: update the latest autosave version instead of adding a new one.',
|
|
9
|
+
paramPublishAllLocales: 'Publish every locale, not only the request locale.',
|
|
10
|
+
paramUnpublishAllLocales: 'Unpublish every locale and set the document back to draft.',
|
|
11
|
+
paramOverrideLock: 'Ignore a lock held by another user. Default false.',
|
|
12
|
+
paramSelectedLocales: 'Copy only these locales to the duplicate. Default: every locale.',
|
|
8
13
|
paramFlattenLocales: 'With `locale=all`, set false to keep localized fields as per-locale objects. Default true.',
|
|
9
14
|
paramLocale: "Locale to return, or `all` for every locale. See the Localization section in the API description.",
|
|
10
15
|
paramFallbackLocale: 'Locale to fall back to for missing localized values, or `none` to disable.',
|
|
@@ -5,6 +5,11 @@ const es = {
|
|
|
5
5
|
paramSortShort: 'Campo por el que ordenar; antepón `-` para orden descendente.',
|
|
6
6
|
paramDraft: 'Devolver versiones en borrador.',
|
|
7
7
|
paramTrash: 'Incluir documentos en la papelera.',
|
|
8
|
+
paramAutosave: 'Guardar como autoguardado: actualiza la última versión autoguardada en lugar de añadir una nueva.',
|
|
9
|
+
paramPublishAllLocales: 'Publicar todos los idiomas, no solo el de la solicitud.',
|
|
10
|
+
paramUnpublishAllLocales: 'Despublicar todos los idiomas y devolver el documento a borrador.',
|
|
11
|
+
paramOverrideLock: 'Ignorar un bloqueo de otro usuario. Por defecto false.',
|
|
12
|
+
paramSelectedLocales: 'Copiar solo estos idiomas al duplicado. Por defecto: todos los idiomas.',
|
|
8
13
|
paramFlattenLocales: 'Con `locale=all`, establécelo en false para mantener los campos localizados como objetos por idioma. Valor por defecto: true.',
|
|
9
14
|
paramLocale: 'Idioma a devolver, o `all` para todos los idiomas. Consulta la sección de Localización en la descripción de la API.',
|
|
10
15
|
paramFallbackLocale: 'Idioma de reserva para los valores localizados que falten, o `none` para desactivarlo.',
|
|
@@ -5,6 +5,11 @@ const et = {
|
|
|
5
5
|
paramSortShort: 'Väli, mille järgi sorteerida; kahanevaks järjestamiseks lisa ette `-`.',
|
|
6
6
|
paramDraft: 'Tagasta mustandversioonid.',
|
|
7
7
|
paramTrash: 'Kaasa prügikasti liigutatud dokumendid.',
|
|
8
|
+
paramAutosave: 'Salvesta automaatsalvestusena: uuendab viimast automaatselt salvestatud versiooni uue lisamise asemel.',
|
|
9
|
+
paramPublishAllLocales: 'Avalda kõik keeled, mitte ainult päringu keel.',
|
|
10
|
+
paramUnpublishAllLocales: 'Tühista kõigi keelte avaldamine ja muuda dokument tagasi mustandiks.',
|
|
11
|
+
paramOverrideLock: 'Eira teise kasutaja lukku. Vaikimisi false.',
|
|
12
|
+
paramSelectedLocales: 'Kopeeri duplikaati ainult need keeled. Vaikimisi: kõik keeled.',
|
|
8
13
|
paramFlattenLocales: 'Väärtusega `locale=all` määra false, et hoida lokaliseeritud välju lokaadipõhiste objektidena. Vaikimisi true.',
|
|
9
14
|
paramLocale: 'Tagastatav lokaat või `all` kõigi lokaatide jaoks. Vaata API kirjelduses jaotist Lokaliseerimine.',
|
|
10
15
|
paramFallbackLocale: 'Lokaat, millele puuduvate lokaliseeritud väärtuste korral tagasi pöörduda, või `none` selle keelamiseks.',
|
|
@@ -5,6 +5,11 @@ const fa = {
|
|
|
5
5
|
paramSortShort: 'فیلدی که بر اساس آن مرتبسازی شود؛ برای ترتیب نزولی پیشوند `-` بگذارید.',
|
|
6
6
|
paramDraft: 'بازگرداندن نسخههای پیشنویس.',
|
|
7
7
|
paramTrash: 'شامل اسناد حذفشده (در سطل زباله) شود.',
|
|
8
|
+
paramAutosave: 'ذخیره بهصورت ذخیرهٔ خودکار: بهجای افزودن نسخهٔ جدید، آخرین نسخهٔ ذخیرهٔ خودکار بهروز میشود.',
|
|
9
|
+
paramPublishAllLocales: 'انتشار همهٔ زبانها، نه فقط زبان درخواست.',
|
|
10
|
+
paramUnpublishAllLocales: 'لغو انتشار همهٔ زبانها و بازگرداندن سند به پیشنویس.',
|
|
11
|
+
paramOverrideLock: 'نادیده گرفتن قفل کاربر دیگر. پیشفرض false.',
|
|
12
|
+
paramSelectedLocales: 'فقط این زبانها در نسخهٔ تکراری کپی شوند. پیشفرض: همهٔ زبانها.',
|
|
8
13
|
paramFlattenLocales: 'با `locale=all`، مقدار false را تنظیم کنید تا فیلدهای محلیسازیشده بهصورت اشیای جداگانه برای هر زبان نگه داشته شوند. مقدار پیشفرض true است.',
|
|
9
14
|
paramLocale: 'زبانی که باید بازگردانده شود، یا `all` برای همه زبانها. به بخش بومیسازی (Localization) در توضیحات API مراجعه کنید.',
|
|
10
15
|
paramFallbackLocale: 'زبانی که در صورت نبودن مقادیر محلیسازیشده به آن بازگشت داده شود، یا `none` برای غیرفعال کردن.',
|
|
@@ -5,6 +5,11 @@ const fr = {
|
|
|
5
5
|
paramSortShort: 'Champ de tri ; préfixez avec `-` pour un ordre décroissant.',
|
|
6
6
|
paramDraft: 'Renvoie les versions brouillon.',
|
|
7
7
|
paramTrash: 'Inclut les documents mis à la corbeille.',
|
|
8
|
+
paramAutosave: "Enregistrer en sauvegarde automatique : met à jour la dernière version enregistrée automatiquement au lieu d'en ajouter une.",
|
|
9
|
+
paramPublishAllLocales: 'Publier toutes les langues, pas seulement celle de la requête.',
|
|
10
|
+
paramUnpublishAllLocales: 'Dépublier toutes les langues et repasser le document en brouillon.',
|
|
11
|
+
paramOverrideLock: 'Ignorer un verrou détenu par un autre utilisateur. Par défaut false.',
|
|
12
|
+
paramSelectedLocales: 'Copier seulement ces langues dans le doublon. Par défaut : toutes les langues.',
|
|
8
13
|
paramFlattenLocales: "Avec `locale=all`, définissez sur false pour conserver les champs localisés sous forme d'objets par locale. true par défaut.",
|
|
9
14
|
paramLocale: "Locale \xe0 renvoyer, ou `all` pour toutes les locales. Voir la section Localisation dans la description de l'API.",
|
|
10
15
|
paramFallbackLocale: 'Locale de repli pour les valeurs localisées manquantes, ou `none` pour désactiver.',
|
|
@@ -5,6 +5,11 @@ const he = {
|
|
|
5
5
|
paramSortShort: 'שדה למיון לפיו; הוסף קידומת `-` לסדר יורד.',
|
|
6
6
|
paramDraft: 'החזרת גרסאות טיוטה.',
|
|
7
7
|
paramTrash: 'כלול מסמכים שנמחקו (באשפה).',
|
|
8
|
+
paramAutosave: 'שמירה כשמירה אוטומטית: מעדכנת את גרסת השמירה האוטומטית האחרונה במקום להוסיף חדשה.',
|
|
9
|
+
paramPublishAllLocales: 'פרסום כל השפות, לא רק שפת הבקשה.',
|
|
10
|
+
paramUnpublishAllLocales: 'ביטול פרסום כל השפות והחזרת המסמך לטיוטה.',
|
|
11
|
+
paramOverrideLock: 'התעלמות מנעילה של משתמש אחר. ברירת מחדל false.',
|
|
12
|
+
paramSelectedLocales: 'העתקת שפות אלה בלבד לשכפול. ברירת מחדל: כל השפות.',
|
|
8
13
|
paramFlattenLocales: 'עם `locale=all`, הגדר false כדי לשמור שדות מתורגמים כאובייקטים לכל לוקאל. ברירת המחדל true.',
|
|
9
14
|
paramLocale: 'הלוקאל להחזרה, או `all` עבור כל הלוקאלים. ראה את סעיף הלוקליזציה בתיאור ה-API.',
|
|
10
15
|
paramFallbackLocale: 'לוקאל לחזרה אחורה עבור ערכים מתורגמים חסרים, או `none` כדי להשבית.',
|