@extravirgin/payload-enchants-translator 1.0.8 → 1.1.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 +231 -21
- package/dist/client/components/CustomButton/CustomButtonWithTranslator.d.ts +2 -2
- package/dist/client/components/CustomButton/CustomButtonWithTranslator.d.ts.map +1 -1
- package/dist/client/components/CustomButton/CustomButtonWithTranslator.js +1 -1
- package/dist/client/components/CustomButton/CustomButtonWithTranslator.js.map +1 -1
- package/dist/client/components/CustomButton/index.js +2 -2
- package/dist/client/components/CustomButton/index.js.map +1 -1
- package/dist/client/components/GlossaryControls/index.d.ts +4 -0
- package/dist/client/components/GlossaryControls/index.d.ts.map +1 -0
- package/dist/client/components/GlossaryControls/index.js +42 -0
- package/dist/client/components/GlossaryControls/index.js.map +1 -0
- package/dist/client/providers/Translator/TranslatorProvider.d.ts.map +1 -1
- package/dist/client/providers/Translator/TranslatorProvider.js +2 -1
- package/dist/client/providers/Translator/TranslatorProvider.js.map +1 -1
- package/dist/exports/client.d.ts +1 -0
- package/dist/exports/client.d.ts.map +1 -1
- package/dist/exports/client.js +1 -0
- package/dist/exports/client.js.map +1 -1
- package/dist/glossary.d.ts +17 -0
- package/dist/glossary.d.ts.map +1 -0
- package/dist/glossary.js +52 -0
- package/dist/glossary.js.map +1 -0
- package/dist/glossaryCollection.d.ts +5 -0
- package/dist/glossaryCollection.d.ts.map +1 -0
- package/dist/glossaryCollection.js +114 -0
- package/dist/glossaryCollection.js.map +1 -0
- package/dist/i18n-translations.d.ts +84 -0
- package/dist/i18n-translations.d.ts.map +1 -1
- package/dist/i18n-translations.js +83 -0
- package/dist/i18n-translations.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +53 -8
- package/dist/index.js.map +1 -1
- package/dist/resolvers/deepl.d.ts +12 -0
- package/dist/resolvers/deepl.d.ts.map +1 -0
- package/dist/resolvers/deepl.js +82 -0
- package/dist/resolvers/deepl.js.map +1 -0
- package/dist/resolvers/deeplGlossary.d.ts +19 -0
- package/dist/resolvers/deeplGlossary.d.ts.map +1 -0
- package/dist/resolvers/deeplGlossary.js +117 -0
- package/dist/resolvers/deeplGlossary.js.map +1 -0
- package/dist/resolvers/types.d.ts +3 -0
- package/dist/resolvers/types.d.ts.map +1 -1
- package/dist/resolvers/types.js.map +1 -1
- package/dist/translate/endpoint.d.ts.map +1 -1
- package/dist/translate/endpoint.js +2 -1
- package/dist/translate/endpoint.js.map +1 -1
- package/dist/translate/findEntityWithConfig.d.ts.map +1 -1
- package/dist/translate/findEntityWithConfig.js +6 -5
- package/dist/translate/findEntityWithConfig.js.map +1 -1
- package/dist/translate/operation.d.ts.map +1 -1
- package/dist/translate/operation.js +5 -1
- package/dist/translate/operation.js.map +1 -1
- package/dist/translate/traverseFields.d.ts.map +1 -1
- package/dist/translate/traverseFields.js +16 -1
- package/dist/translate/traverseFields.js.map +1 -1
- package/dist/translate/updateEntity.d.ts.map +1 -1
- package/dist/translate/updateEntity.js +3 -2
- package/dist/translate/updateEntity.js.map +1 -1
- package/dist/types.d.ts +10 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +53 -22
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { CollectionSlug, Config, GlobalSlug, Plugin } from 'payload';\nimport { deepMerge } from 'payload/shared';\n\nimport { CustomButton } from './client/components/CustomButton';\nimport { translations } from './i18n-translations';\nimport { translateEndpoint } from './translate/endpoint';\nimport { translateOperation } from './translate/operation';\nimport type { TranslatorConfig } from './types';\n\nexport { copyResolver } from './resolvers/copy';\n\nexport { googleResolver } from './resolvers/google';\n\nexport { libreResolver } from './resolvers/libreTranslate';\n\nexport { openAIResolver } from './resolvers/openAI';\nexport * from './resolvers/types';\n\nexport { translateOperation };\n\nexport const translator: (pluginConfig: TranslatorConfig) => Plugin = (pluginConfig) => {\n return (config) => {\n if (pluginConfig.disabled || !config.localization || config.localization.locales.length < 2)\n return config;\n\n const updatedConfig: Config = {\n ...config,\n admin: {\n ...(config.admin ?? {}),\n custom: {\n ...(config.admin?.custom ?? {}),\n translator: {\n basePath: pluginConfig.basePath ?? '',\n resolvers: pluginConfig.resolvers.map(({ key }) => ({ key })),\n },\n },\n },\n collections:\n config.collections?.map((collection) => {\n if (!pluginConfig.collections.includes(collection.slug as CollectionSlug))\n return collection;\n\n return {\n ...collection,\n admin: {\n ...(collection.admin ?? {}),\n components: {\n ...(collection.admin?.components ?? {}),\n edit: {\n ...(collection.admin?.components?.edit ?? {}),\n PublishButton: CustomButton('publish', pluginConfig.disabledLocales ?? []),\n SaveButton: CustomButton('save', pluginConfig.disabledLocales ?? []),\n },\n },\n },\n };\n }) ?? [],\n custom: {\n ...(config.custom ?? {}),\n translator: {\n basePath: pluginConfig.basePath ?? '',\n resolvers: pluginConfig.resolvers,\n },\n },\n endpoints: [\n ...(config.endpoints ?? []),\n {\n handler: translateEndpoint,\n method: 'post',\n path: '/translator/translate',\n },\n ],\n globals:\n config.globals?.map((global) => {\n if (!pluginConfig.globals.includes(global.slug as GlobalSlug)) return global;\n\n return {\n ...global,\n admin: {\n ...(global.admin ?? {}),\n components: {\n ...(global.admin?.components ?? {}),\n elements: {\n ...(global.admin?.components?.elements ?? {}),\n PublishButton: CustomButton('publish', pluginConfig.disabledLocales ?? []),\n SaveButton: CustomButton('save', pluginConfig.disabledLocales ?? []),\n },\n },\n },\n };\n }) ?? [],\n
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { CollectionSlug, Config, GlobalSlug, PayloadRequest, Plugin } from 'payload';\nimport { APIError } from 'payload';\nimport { deepMerge } from 'payload/shared';\n\nimport { CustomButton } from './client/components/CustomButton';\nimport { createGlossaryEntriesCollection } from './glossaryCollection';\nimport { translations, translatorT } from './i18n-translations';\nimport { translateEndpoint } from './translate/endpoint';\nimport { translateOperation } from './translate/operation';\nimport type { TranslatorConfig } from './types';\n\nexport type { GlossaryConfig } from './glossary';\n\nexport { copyResolver } from './resolvers/copy';\n\nexport type { DeepLResolverConfig } from './resolvers/deepl';\n\nexport { deeplResolver } from './resolvers/deepl';\n\nexport { googleResolver } from './resolvers/google';\n\nexport { libreResolver } from './resolvers/libreTranslate';\n\nexport { openAIResolver } from './resolvers/openAI';\nexport * from './resolvers/types';\n\nexport { translateOperation };\n\nexport const translator: (pluginConfig: TranslatorConfig) => Plugin = (pluginConfig) => {\n return (config) => {\n config = {\n ...config,\n i18n: {\n ...config.i18n,\n translations: deepMerge(translations, config.i18n?.translations ?? {}),\n },\n };\n // Keep the opt-in glossary schema available even when translation is disabled.\n if (pluginConfig.glossary) {\n const sync = async (req: PayloadRequest, entry?: Record<string, string>) => {\n const resolver = pluginConfig.resolvers.find((item) => item.key === 'deepl');\n\n if (!resolver?.glossary)\n throw new APIError(translatorT(req.t, 'glossary_missingResolver'), 400, undefined, true);\n await resolver.glossary.sync(req, entry);\n };\n\n const entries = createGlossaryEntriesCollection(\n pluginConfig.glossary,\n pluginConfig.basePath ?? '',\n sync,\n );\n\n if (config.collections?.some((collection) => collection.slug === entries.slug)) {\n throw new Error(`A collection with the glossary slug \"${entries.slug}\" already exists.`);\n }\n config = {\n ...config,\n collections: [...(config.collections ?? []), entries],\n endpoints: [\n ...(config.endpoints ?? []),\n {\n handler: async (req: PayloadRequest) => {\n try {\n await sync(req);\n\n return Response.json({ success: true });\n } catch (error) {\n req.payload.logger.error(error);\n\n return Response.json(\n {\n error:\n error instanceof APIError && error.isPublic\n ? error.message\n : translatorT(req.t, 'glossary_syncError'),\n },\n { status: 400 },\n );\n }\n },\n method: 'post',\n path: '/translator/glossary/sync',\n },\n ],\n };\n }\n if (pluginConfig.disabled || !config.localization || config.localization.locales.length < 2)\n return config;\n\n const updatedConfig: Config = {\n ...config,\n admin: {\n ...(config.admin ?? {}),\n custom: {\n ...(config.admin?.custom ?? {}),\n translator: {\n basePath: pluginConfig.basePath ?? '',\n resolvers: pluginConfig.resolvers.map(({ key }) => ({ key })),\n },\n },\n },\n collections:\n config.collections?.map((collection) => {\n if (!pluginConfig.collections.includes(collection.slug as CollectionSlug))\n return collection;\n\n return {\n ...collection,\n admin: {\n ...(collection.admin ?? {}),\n components: {\n ...(collection.admin?.components ?? {}),\n edit: {\n ...(collection.admin?.components?.edit ?? {}),\n PublishButton: CustomButton('publish', pluginConfig.disabledLocales ?? []),\n SaveButton: CustomButton('save', pluginConfig.disabledLocales ?? []),\n },\n },\n },\n };\n }) ?? [],\n custom: {\n ...(config.custom ?? {}),\n translator: {\n basePath: pluginConfig.basePath ?? '',\n resolvers: pluginConfig.resolvers,\n },\n },\n endpoints: [\n ...(config.endpoints ?? []),\n {\n handler: translateEndpoint,\n method: 'post',\n path: '/translator/translate',\n },\n ],\n globals:\n config.globals?.map((global) => {\n if (!pluginConfig.globals.includes(global.slug as GlobalSlug)) return global;\n\n return {\n ...global,\n admin: {\n ...(global.admin ?? {}),\n components: {\n ...(global.admin?.components ?? {}),\n elements: {\n ...(global.admin?.components?.elements ?? {}),\n PublishButton: CustomButton('publish', pluginConfig.disabledLocales ?? []),\n SaveButton: CustomButton('save', pluginConfig.disabledLocales ?? []),\n },\n },\n },\n };\n }) ?? [],\n };\n\n return updatedConfig;\n };\n};\n"],"names":["APIError","deepMerge","CustomButton","createGlossaryEntriesCollection","translations","translatorT","translateEndpoint","translateOperation","copyResolver","deeplResolver","googleResolver","libreResolver","openAIResolver","translator","pluginConfig","config","i18n","glossary","sync","req","entry","resolver","resolvers","find","item","key","t","undefined","entries","basePath","collections","some","collection","slug","Error","endpoints","handler","Response","json","success","error","payload","logger","isPublic","message","status","method","path","disabled","localization","locales","length","updatedConfig","admin","custom","map","includes","components","edit","PublishButton","disabledLocales","SaveButton","globals","global","elements"],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { GlossaryConfig } from '../glossary';
|
|
2
|
+
import type { TranslateResolver } from './types';
|
|
3
|
+
export type DeepLResolverConfig = {
|
|
4
|
+
apiKey: string;
|
|
5
|
+
chunkLength?: number;
|
|
6
|
+
glossary?: GlossaryConfig;
|
|
7
|
+
glossaryId?: string;
|
|
8
|
+
sourceLocaleMap?: Record<string, string>;
|
|
9
|
+
targetLocaleMap?: Record<string, string>;
|
|
10
|
+
};
|
|
11
|
+
export declare const deeplResolver: ({ apiKey, chunkLength, glossary, glossaryId: configuredGlossaryId, sourceLocaleMap, targetLocaleMap, }: DeepLResolverConfig) => TranslateResolver;
|
|
12
|
+
//# sourceMappingURL=deepl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deepl.d.ts","sourceRoot":"","sources":["../../src/resolvers/deepl.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C,CAAC;AAIF,eAAO,MAAM,aAAa,2GAOvB,mBAAmB,KAAG,iBAiGxB,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { chunkArray } from '../utils/chunkArray';
|
|
2
|
+
const hasSpecialUnicodeCharacters = (text)=>/[\u0300-\u036f\u0336]/.test(text);
|
|
3
|
+
export const deeplResolver = ({ apiKey, chunkLength = 100, glossary, glossaryId: configuredGlossaryId, sourceLocaleMap = {}, targetLocaleMap = {} })=>{
|
|
4
|
+
if (!Number.isInteger(chunkLength) || chunkLength < 1) {
|
|
5
|
+
throw new Error('DeepL chunkLength must be a positive integer.');
|
|
6
|
+
}
|
|
7
|
+
const glossaryId = configuredGlossaryId?.trim() || undefined;
|
|
8
|
+
if (glossaryId && !glossary) {
|
|
9
|
+
throw new Error('DeepL glossary options require glossary configuration.');
|
|
10
|
+
}
|
|
11
|
+
return {
|
|
12
|
+
...glossary ? {
|
|
13
|
+
glossary: {
|
|
14
|
+
sync: async (req, entry)=>{
|
|
15
|
+
const { DeepLClient } = await import('deepl-node');
|
|
16
|
+
const { syncDeepLGlossary } = await import('./deeplGlossary');
|
|
17
|
+
return syncDeepLGlossary({
|
|
18
|
+
client: new DeepLClient(apiKey, {
|
|
19
|
+
maxRetries: 0,
|
|
20
|
+
minTimeout: 60000
|
|
21
|
+
}),
|
|
22
|
+
entry,
|
|
23
|
+
glossary,
|
|
24
|
+
glossaryId,
|
|
25
|
+
req,
|
|
26
|
+
sourceLocaleMap,
|
|
27
|
+
targetLocaleMap
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
} : {},
|
|
32
|
+
key: 'deepl',
|
|
33
|
+
resolve: async ({ localeFrom, localeTo, req, texts })=>{
|
|
34
|
+
if (!texts.some((text)=>text.trim())) {
|
|
35
|
+
return {
|
|
36
|
+
success: true,
|
|
37
|
+
translatedTexts: texts.map(()=>'')
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
// Optional peer dependency: other resolvers do not load the DeepL SDK.
|
|
41
|
+
const { DeepLClient } = await import('deepl-node');
|
|
42
|
+
const client = new DeepLClient(apiKey);
|
|
43
|
+
const sourceLang = sourceLocaleMap[localeFrom] ?? localeFrom;
|
|
44
|
+
const targetLang = targetLocaleMap[localeTo] ?? localeTo;
|
|
45
|
+
let translationGlossaryId;
|
|
46
|
+
if (glossary && localeFrom === glossary.sourceLocale && glossary.targetLocales.includes(localeTo)) {
|
|
47
|
+
const { getDeepLGlossaryId } = await import('./deeplGlossary');
|
|
48
|
+
translationGlossaryId = await getDeepLGlossaryId({
|
|
49
|
+
glossary,
|
|
50
|
+
glossaryId,
|
|
51
|
+
req,
|
|
52
|
+
sourceLocaleMap,
|
|
53
|
+
targetLocale: localeTo,
|
|
54
|
+
targetLocaleMap
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
const translatedTexts = [];
|
|
58
|
+
for (const batch of chunkArray(texts, chunkLength)){
|
|
59
|
+
const context = batch.filter((text)=>!hasSpecialUnicodeCharacters(text)).join(' ');
|
|
60
|
+
// Settle the batch before returning a result or propagating an error.
|
|
61
|
+
const results = await Promise.allSettled(batch.map((text)=>text.trim() ? client.translateText(text, sourceLang, targetLang, {
|
|
62
|
+
context,
|
|
63
|
+
glossary: translationGlossaryId,
|
|
64
|
+
modelType: hasSpecialUnicodeCharacters(text) ? 'latency_optimized' : 'prefer_quality_optimized',
|
|
65
|
+
tagHandling: 'html'
|
|
66
|
+
}) : Promise.resolve({
|
|
67
|
+
text: ''
|
|
68
|
+
})));
|
|
69
|
+
for (const result of results){
|
|
70
|
+
if (result.status === 'rejected') throw result.reason;
|
|
71
|
+
translatedTexts.push(result.value.text);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
success: true,
|
|
76
|
+
translatedTexts
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
//# sourceMappingURL=deepl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/resolvers/deepl.ts"],"sourcesContent":["import type { SourceLanguageCode, TargetLanguageCode } from 'deepl-node';\n\nimport type { GlossaryConfig } from '../glossary';\nimport { chunkArray } from '../utils/chunkArray';\nimport type { TranslateResolver } from './types';\n\nexport type DeepLResolverConfig = {\n apiKey: string;\n chunkLength?: number;\n glossary?: GlossaryConfig;\n glossaryId?: string;\n sourceLocaleMap?: Record<string, string>;\n targetLocaleMap?: Record<string, string>;\n};\n\nconst hasSpecialUnicodeCharacters = (text: string) => /[\\u0300-\\u036f\\u0336]/.test(text);\n\nexport const deeplResolver = ({\n apiKey,\n chunkLength = 100,\n glossary,\n glossaryId: configuredGlossaryId,\n sourceLocaleMap = {},\n targetLocaleMap = {},\n}: DeepLResolverConfig): TranslateResolver => {\n if (!Number.isInteger(chunkLength) || chunkLength < 1) {\n throw new Error('DeepL chunkLength must be a positive integer.');\n }\n\n const glossaryId = configuredGlossaryId?.trim() || undefined;\n\n if (glossaryId && !glossary) {\n throw new Error('DeepL glossary options require glossary configuration.');\n }\n\n return {\n ...(glossary\n ? {\n glossary: {\n sync: async (req, entry) => {\n const { DeepLClient } = await import('deepl-node');\n\n const { syncDeepLGlossary } = await import('./deeplGlossary');\n\n return syncDeepLGlossary({\n client: new DeepLClient(apiKey, { maxRetries: 0, minTimeout: 60000 }),\n entry,\n glossary,\n glossaryId,\n req,\n sourceLocaleMap,\n targetLocaleMap,\n });\n },\n },\n }\n : {}),\n key: 'deepl',\n resolve: async ({ localeFrom, localeTo, req, texts }) => {\n if (!texts.some((text) => text.trim())) {\n return { success: true, translatedTexts: texts.map(() => '') };\n }\n\n // Optional peer dependency: other resolvers do not load the DeepL SDK.\n const { DeepLClient } = await import('deepl-node');\n\n const client = new DeepLClient(apiKey);\n\n const sourceLang = (sourceLocaleMap[localeFrom] ?? localeFrom) as SourceLanguageCode;\n\n const targetLang = (targetLocaleMap[localeTo] ?? localeTo) as TargetLanguageCode;\n\n let translationGlossaryId: string | undefined;\n\n if (\n glossary &&\n localeFrom === glossary.sourceLocale &&\n glossary.targetLocales.includes(localeTo)\n ) {\n const { getDeepLGlossaryId } = await import('./deeplGlossary');\n\n translationGlossaryId = await getDeepLGlossaryId({\n glossary,\n glossaryId,\n req,\n sourceLocaleMap,\n targetLocale: localeTo,\n targetLocaleMap,\n });\n }\n\n const translatedTexts: string[] = [];\n\n for (const batch of chunkArray(texts, chunkLength)) {\n const context = batch.filter((text) => !hasSpecialUnicodeCharacters(text)).join(' ');\n\n // Settle the batch before returning a result or propagating an error.\n const results = await Promise.allSettled(\n batch.map((text) =>\n text.trim()\n ? client.translateText(text, sourceLang, targetLang, {\n context,\n glossary: translationGlossaryId,\n modelType: hasSpecialUnicodeCharacters(text)\n ? 'latency_optimized'\n : 'prefer_quality_optimized',\n tagHandling: 'html',\n })\n : Promise.resolve({ text: '' }),\n ),\n );\n\n for (const result of results) {\n if (result.status === 'rejected') throw result.reason;\n translatedTexts.push(result.value.text);\n }\n }\n\n return { success: true, translatedTexts };\n },\n };\n};\n"],"names":["chunkArray","hasSpecialUnicodeCharacters","text","test","deeplResolver","apiKey","chunkLength","glossary","glossaryId","configuredGlossaryId","sourceLocaleMap","targetLocaleMap","Number","isInteger","Error","trim","undefined","sync","req","entry","DeepLClient","syncDeepLGlossary","client","maxRetries","minTimeout","key","resolve","localeFrom","localeTo","texts","some","success","translatedTexts","map","sourceLang","targetLang","translationGlossaryId","sourceLocale","targetLocales","includes","getDeepLGlossaryId","targetLocale","batch","context","filter","join","results","Promise","allSettled","translateText","modelType","tagHandling","result","status","reason","push","value"],"mappings":"AAGA,SAASA,UAAU,QAAQ,sBAAsB;AAYjD,MAAMC,8BAA8B,CAACC,OAAiB,wBAAwBC,IAAI,CAACD;AAEnF,OAAO,MAAME,gBAAgB,CAAC,EAC5BC,MAAM,EACNC,cAAc,GAAG,EACjBC,QAAQ,EACRC,YAAYC,oBAAoB,EAChCC,kBAAkB,CAAC,CAAC,EACpBC,kBAAkB,CAAC,CAAC,EACA;IACpB,IAAI,CAACC,OAAOC,SAAS,CAACP,gBAAgBA,cAAc,GAAG;QACrD,MAAM,IAAIQ,MAAM;IAClB;IAEA,MAAMN,aAAaC,sBAAsBM,UAAUC;IAEnD,IAAIR,cAAc,CAACD,UAAU;QAC3B,MAAM,IAAIO,MAAM;IAClB;IAEA,OAAO;QACL,GAAIP,WACA;YACEA,UAAU;gBACRU,MAAM,OAAOC,KAAKC;oBAChB,MAAM,EAAEC,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC;oBAErC,MAAM,EAAEC,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC;oBAE3C,OAAOA,kBAAkB;wBACvBC,QAAQ,IAAIF,YAAYf,QAAQ;4BAAEkB,YAAY;4BAAGC,YAAY;wBAAM;wBACnEL;wBACAZ;wBACAC;wBACAU;wBACAR;wBACAC;oBACF;gBACF;YACF;QACF,IACA,CAAC,CAAC;QACNc,KAAK;QACLC,SAAS,OAAO,EAAEC,UAAU,EAAEC,QAAQ,EAAEV,GAAG,EAAEW,KAAK,EAAE;YAClD,IAAI,CAACA,MAAMC,IAAI,CAAC,CAAC5B,OAASA,KAAKa,IAAI,KAAK;gBACtC,OAAO;oBAAEgB,SAAS;oBAAMC,iBAAiBH,MAAMI,GAAG,CAAC,IAAM;gBAAI;YAC/D;YAEA,uEAAuE;YACvE,MAAM,EAAEb,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC;YAErC,MAAME,SAAS,IAAIF,YAAYf;YAE/B,MAAM6B,aAAcxB,eAAe,CAACiB,WAAW,IAAIA;YAEnD,MAAMQ,aAAcxB,eAAe,CAACiB,SAAS,IAAIA;YAEjD,IAAIQ;YAEJ,IACE7B,YACAoB,eAAepB,SAAS8B,YAAY,IACpC9B,SAAS+B,aAAa,CAACC,QAAQ,CAACX,WAChC;gBACA,MAAM,EAAEY,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC;gBAE5CJ,wBAAwB,MAAMI,mBAAmB;oBAC/CjC;oBACAC;oBACAU;oBACAR;oBACA+B,cAAcb;oBACdjB;gBACF;YACF;YAEA,MAAMqB,kBAA4B,EAAE;YAEpC,KAAK,MAAMU,SAAS1C,WAAW6B,OAAOvB,aAAc;gBAClD,MAAMqC,UAAUD,MAAME,MAAM,CAAC,CAAC1C,OAAS,CAACD,4BAA4BC,OAAO2C,IAAI,CAAC;gBAEhF,sEAAsE;gBACtE,MAAMC,UAAU,MAAMC,QAAQC,UAAU,CACtCN,MAAMT,GAAG,CAAC,CAAC/B,OACTA,KAAKa,IAAI,KACLO,OAAO2B,aAAa,CAAC/C,MAAMgC,YAAYC,YAAY;wBACjDQ;wBACApC,UAAU6B;wBACVc,WAAWjD,4BAA4BC,QACnC,sBACA;wBACJiD,aAAa;oBACf,KACAJ,QAAQrB,OAAO,CAAC;wBAAExB,MAAM;oBAAG;gBAInC,KAAK,MAAMkD,UAAUN,QAAS;oBAC5B,IAAIM,OAAOC,MAAM,KAAK,YAAY,MAAMD,OAAOE,MAAM;oBACrDtB,gBAAgBuB,IAAI,CAACH,OAAOI,KAAK,CAACtD,IAAI;gBACxC;YACF;YAEA,OAAO;gBAAE6B,SAAS;gBAAMC;YAAgB;QAC1C;IACF;AACF,EAAE"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { DeepLClient } from 'deepl-node';
|
|
2
|
+
import type { PayloadRequest } from 'payload';
|
|
3
|
+
import type { GlossaryConfig } from '../glossary';
|
|
4
|
+
type Options = {
|
|
5
|
+
glossary: GlossaryConfig;
|
|
6
|
+
glossaryId?: string;
|
|
7
|
+
req: PayloadRequest;
|
|
8
|
+
sourceLocaleMap?: Record<string, string>;
|
|
9
|
+
targetLocaleMap?: Record<string, string>;
|
|
10
|
+
};
|
|
11
|
+
export declare const getDeepLGlossaryId: (options: {
|
|
12
|
+
targetLocale: string;
|
|
13
|
+
} & Options) => Promise<string | undefined>;
|
|
14
|
+
export declare const syncDeepLGlossary: (options: {
|
|
15
|
+
client: DeepLClient;
|
|
16
|
+
entry?: Record<string, string>;
|
|
17
|
+
} & Options) => Promise<void>;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=deeplGlossary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deeplGlossary.d.ts","sourceRoot":"","sources":["../../src/resolvers/deeplGlossary.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,KAAK,EAAkB,cAAc,EAAE,MAAM,SAAS,CAAC;AAG9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAKlD,KAAK,OAAO,GAAG;IACb,QAAQ,EAAE,cAAc,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,cAAc,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C,CAAC;AAcF,eAAO,MAAM,kBAAkB,YAAmB;IAAE,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,gCAqBnF,CAAC;AAGF,eAAO,MAAM,iBAAiB,YACnB;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,OAAO,KACzE,OAAO,CAAC,IAAI,CAwFd,CAAC"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { GlossaryEntries } from 'deepl-node';
|
|
2
|
+
import { APIError } from 'payload';
|
|
3
|
+
import { validateGlossaryEntries } from '../glossary';
|
|
4
|
+
import { getGlossaryEntriesSlug } from '../glossaryCollection';
|
|
5
|
+
import { translatorT } from '../i18n-translations';
|
|
6
|
+
const language = (locale)=>locale.toLowerCase().split('-')[0];
|
|
7
|
+
const requireAccess = async ({ glossary, req }, write = false)=>{
|
|
8
|
+
if (await glossary.access.read({
|
|
9
|
+
req
|
|
10
|
+
}) !== true || write && await glossary.access.update({
|
|
11
|
+
req
|
|
12
|
+
}) !== true) {
|
|
13
|
+
throw new APIError(translatorT(req.t, 'glossary_accessDenied'), 403, undefined, true);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
// An omitted target translation does not require a DeepL dictionary.
|
|
17
|
+
export const getDeepLGlossaryId = async (options)=>{
|
|
18
|
+
await requireAccess(options);
|
|
19
|
+
const { glossary, glossaryId, req, targetLocale } = options;
|
|
20
|
+
const result = await req.payload.find({
|
|
21
|
+
collection: getGlossaryEntriesSlug(glossary),
|
|
22
|
+
depth: 0,
|
|
23
|
+
limit: 1,
|
|
24
|
+
overrideAccess: false,
|
|
25
|
+
req,
|
|
26
|
+
select: {
|
|
27
|
+
[targetLocale]: true
|
|
28
|
+
},
|
|
29
|
+
where: {
|
|
30
|
+
and: [
|
|
31
|
+
{
|
|
32
|
+
[targetLocale]: {
|
|
33
|
+
exists: true
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
[targetLocale]: {
|
|
38
|
+
not_equals: ''
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
if (!result.docs.length) return undefined;
|
|
45
|
+
if (!glossaryId) throw new APIError(translatorT(req.t, 'glossary_missingID'), 400, undefined, true);
|
|
46
|
+
return glossaryId;
|
|
47
|
+
};
|
|
48
|
+
// Entry saves merge one item. Only the manual action reads and replaces full dictionaries.
|
|
49
|
+
export const syncDeepLGlossary = async (options)=>{
|
|
50
|
+
await requireAccess(options, true);
|
|
51
|
+
const { client, entry, glossary, glossaryId, req } = options;
|
|
52
|
+
if (!glossaryId) throw new APIError(translatorT(req.t, 'glossary_missingID'), 400, undefined, true);
|
|
53
|
+
const sourceLangCode = language(options.sourceLocaleMap?.[glossary.sourceLocale] ?? glossary.sourceLocale);
|
|
54
|
+
const dictionaries = glossary.targetLocales.map((locale)=>({
|
|
55
|
+
entries: new GlossaryEntries(),
|
|
56
|
+
locale,
|
|
57
|
+
sourceLangCode,
|
|
58
|
+
targetLangCode: language(options.targetLocaleMap?.[locale] ?? locale)
|
|
59
|
+
}));
|
|
60
|
+
if (new Set(dictionaries.map((item)=>item.targetLangCode)).size !== dictionaries.length) {
|
|
61
|
+
throw new APIError(translatorT(req.t, 'glossary_distinctLanguages'), 400, undefined, true);
|
|
62
|
+
}
|
|
63
|
+
let bytes = 0;
|
|
64
|
+
const add = (doc)=>{
|
|
65
|
+
const validation = validateGlossaryEntries([
|
|
66
|
+
doc
|
|
67
|
+
], glossary, req.t);
|
|
68
|
+
if (validation !== true) throw new APIError(validation, 400, undefined, true);
|
|
69
|
+
const source = doc[glossary.sourceLocale].trim();
|
|
70
|
+
for (const dictionary of dictionaries){
|
|
71
|
+
const target = doc[dictionary.locale]?.trim();
|
|
72
|
+
if (!target) continue;
|
|
73
|
+
bytes += Buffer.byteLength(`${source}\t${target}\n`, 'utf8');
|
|
74
|
+
if (bytes > 10 * 1024 * 1024) throw new APIError(translatorT(req.t, 'glossary_tooLarge'), 400, undefined, true);
|
|
75
|
+
dictionary.entries.add(source, target);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
if (entry) {
|
|
79
|
+
add(entry);
|
|
80
|
+
for (const dictionary of dictionaries){
|
|
81
|
+
if (Object.keys(dictionary.entries.entries()).length) {
|
|
82
|
+
await client.updateMultilingualGlossaryDictionary(glossaryId, dictionary);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
for(let page = 1;; page++){
|
|
88
|
+
const result = await req.payload.find({
|
|
89
|
+
collection: getGlossaryEntriesSlug(glossary),
|
|
90
|
+
depth: 0,
|
|
91
|
+
limit: 1000,
|
|
92
|
+
overrideAccess: false,
|
|
93
|
+
page,
|
|
94
|
+
req,
|
|
95
|
+
select: Object.fromEntries([
|
|
96
|
+
glossary.sourceLocale,
|
|
97
|
+
...glossary.targetLocales
|
|
98
|
+
].map((locale)=>[
|
|
99
|
+
locale,
|
|
100
|
+
true
|
|
101
|
+
])),
|
|
102
|
+
sort: 'sourceKey'
|
|
103
|
+
});
|
|
104
|
+
for (const doc of result.docs)add(doc);
|
|
105
|
+
if (!result.hasNextPage) break;
|
|
106
|
+
}
|
|
107
|
+
const remote = await client.getMultilingualGlossary(glossaryId);
|
|
108
|
+
for (const dictionary of dictionaries){
|
|
109
|
+
if (Object.keys(dictionary.entries.entries()).length) {
|
|
110
|
+
await client.replaceMultilingualGlossaryDictionary(glossaryId, dictionary);
|
|
111
|
+
} else if (remote.dictionaries.some((item)=>language(item.sourceLangCode) === sourceLangCode && language(item.targetLangCode) === dictionary.targetLangCode)) {
|
|
112
|
+
await client.deleteMultilingualGlossaryDictionary(glossaryId, sourceLangCode, dictionary.targetLangCode);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
//# sourceMappingURL=deeplGlossary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/resolvers/deeplGlossary.ts"],"sourcesContent":["import type { DeepLClient } from 'deepl-node';\nimport { GlossaryEntries } from 'deepl-node';\nimport type { CollectionSlug, PayloadRequest } from 'payload';\nimport { APIError } from 'payload';\n\nimport type { GlossaryConfig } from '../glossary';\nimport { validateGlossaryEntries } from '../glossary';\nimport { getGlossaryEntriesSlug } from '../glossaryCollection';\nimport { translatorT } from '../i18n-translations';\n\ntype Options = {\n glossary: GlossaryConfig;\n glossaryId?: string;\n req: PayloadRequest;\n sourceLocaleMap?: Record<string, string>;\n targetLocaleMap?: Record<string, string>;\n};\n\nconst language = (locale: string) => locale.toLowerCase().split('-')[0];\n\nconst requireAccess = async ({ glossary, req }: Options, write = false) => {\n if (\n (await glossary.access.read({ req })) !== true ||\n (write && (await glossary.access.update({ req })) !== true)\n ) {\n throw new APIError(translatorT(req.t, 'glossary_accessDenied'), 403, undefined, true);\n }\n};\n\n// An omitted target translation does not require a DeepL dictionary.\nexport const getDeepLGlossaryId = async (options: { targetLocale: string } & Options) => {\n await requireAccess(options);\n const { glossary, glossaryId, req, targetLocale } = options;\n\n const result = await req.payload.find({\n collection: getGlossaryEntriesSlug(glossary) as CollectionSlug,\n depth: 0,\n limit: 1,\n overrideAccess: false,\n req,\n select: { [targetLocale]: true },\n where: {\n and: [{ [targetLocale]: { exists: true } }, { [targetLocale]: { not_equals: '' } }],\n },\n });\n\n if (!result.docs.length) return undefined;\n if (!glossaryId)\n throw new APIError(translatorT(req.t, 'glossary_missingID'), 400, undefined, true);\n\n return glossaryId;\n};\n\n// Entry saves merge one item. Only the manual action reads and replaces full dictionaries.\nexport const syncDeepLGlossary = async (\n options: { client: DeepLClient; entry?: Record<string, string> } & Options,\n): Promise<void> => {\n await requireAccess(options, true);\n const { client, entry, glossary, glossaryId, req } = options;\n\n if (!glossaryId)\n throw new APIError(translatorT(req.t, 'glossary_missingID'), 400, undefined, true);\n\n const sourceLangCode = language(\n options.sourceLocaleMap?.[glossary.sourceLocale] ?? glossary.sourceLocale,\n );\n\n const dictionaries = glossary.targetLocales.map((locale) => ({\n entries: new GlossaryEntries(),\n locale,\n sourceLangCode,\n targetLangCode: language(options.targetLocaleMap?.[locale] ?? locale),\n }));\n\n if (new Set(dictionaries.map((item) => item.targetLangCode)).size !== dictionaries.length) {\n throw new APIError(translatorT(req.t, 'glossary_distinctLanguages'), 400, undefined, true);\n }\n let bytes = 0;\n\n const add = (doc: Record<string, string>) => {\n const validation = validateGlossaryEntries([doc], glossary, req.t);\n\n if (validation !== true) throw new APIError(validation, 400, undefined, true);\n const source = doc[glossary.sourceLocale].trim();\n\n for (const dictionary of dictionaries) {\n const target = doc[dictionary.locale]?.trim();\n\n if (!target) continue;\n bytes += Buffer.byteLength(`${source}\\t${target}\\n`, 'utf8');\n if (bytes > 10 * 1024 * 1024)\n throw new APIError(translatorT(req.t, 'glossary_tooLarge'), 400, undefined, true);\n dictionary.entries.add(source, target);\n }\n };\n\n if (entry) {\n add(entry);\n for (const dictionary of dictionaries) {\n if (Object.keys(dictionary.entries.entries()).length) {\n await client.updateMultilingualGlossaryDictionary(glossaryId, dictionary);\n }\n }\n\n return;\n }\n\n for (let page = 1; ; page++) {\n const result = await req.payload.find({\n collection: getGlossaryEntriesSlug(glossary) as CollectionSlug,\n depth: 0,\n limit: 1000,\n overrideAccess: false,\n page,\n req,\n select: Object.fromEntries(\n [glossary.sourceLocale, ...glossary.targetLocales].map((locale) => [locale, true]),\n ),\n sort: 'sourceKey',\n });\n\n for (const doc of result.docs) add(doc as unknown as Record<string, string>);\n if (!result.hasNextPage) break;\n }\n\n const remote = await client.getMultilingualGlossary(glossaryId);\n\n for (const dictionary of dictionaries) {\n if (Object.keys(dictionary.entries.entries()).length) {\n await client.replaceMultilingualGlossaryDictionary(glossaryId, dictionary);\n } else if (\n remote.dictionaries.some(\n (item) =>\n language(item.sourceLangCode) === sourceLangCode &&\n language(item.targetLangCode) === dictionary.targetLangCode,\n )\n ) {\n await client.deleteMultilingualGlossaryDictionary(\n glossaryId,\n sourceLangCode,\n dictionary.targetLangCode,\n );\n }\n }\n};\n"],"names":["GlossaryEntries","APIError","validateGlossaryEntries","getGlossaryEntriesSlug","translatorT","language","locale","toLowerCase","split","requireAccess","glossary","req","write","access","read","update","t","undefined","getDeepLGlossaryId","options","glossaryId","targetLocale","result","payload","find","collection","depth","limit","overrideAccess","select","where","and","exists","not_equals","docs","length","syncDeepLGlossary","client","entry","sourceLangCode","sourceLocaleMap","sourceLocale","dictionaries","targetLocales","map","entries","targetLangCode","targetLocaleMap","Set","item","size","bytes","add","doc","validation","source","trim","dictionary","target","Buffer","byteLength","Object","keys","updateMultilingualGlossaryDictionary","page","fromEntries","sort","hasNextPage","remote","getMultilingualGlossary","replaceMultilingualGlossaryDictionary","some","deleteMultilingualGlossaryDictionary"],"mappings":"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"}
|
|
@@ -14,6 +14,9 @@ export type TranslateResolverResponse = {
|
|
|
14
14
|
translatedTexts: string[];
|
|
15
15
|
};
|
|
16
16
|
export type TranslateResolver = {
|
|
17
|
+
glossary?: {
|
|
18
|
+
sync: (req: PayloadRequest, entry?: Record<string, string>) => Promise<void>;
|
|
19
|
+
};
|
|
17
20
|
key: string;
|
|
18
21
|
resolve: (args: TranslateResolverArgs) => Promise<TranslateResolverResponse> | TranslateResolverResponse;
|
|
19
22
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/resolvers/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,MAAM,MAAM,qBAAqB,GAAG;IAClC,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,cAAc,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GACjC;IACE,OAAO,EAAE,KAAK,CAAC;CAChB,GACD;IACE,OAAO,EAAE,IAAI,CAAC;IACd,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B,CAAC;AAEN,MAAM,MAAM,iBAAiB,GAAG;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,CACP,IAAI,EAAE,qBAAqB,KACxB,OAAO,CAAC,yBAAyB,CAAC,GAAG,yBAAyB,CAAC;CACrE,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/resolvers/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,MAAM,MAAM,qBAAqB,GAAG;IAClC,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,cAAc,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GACjC;IACE,OAAO,EAAE,KAAK,CAAC;CAChB,GACD;IACE,OAAO,EAAE,IAAI,CAAC;IACd,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B,CAAC;AAEN,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,EAAE;QACT,IAAI,EAAE,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KAC9E,CAAC;IACF,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,CACP,IAAI,EAAE,qBAAqB,KACxB,OAAO,CAAC,yBAAyB,CAAC,GAAG,yBAAyB,CAAC;CACrE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/resolvers/types.ts"],"sourcesContent":["import type { PayloadRequest } from 'payload';\n\nexport type TranslateResolverArgs = {\n /** Locale to translate from */\n localeFrom: string;\n /** Locale to translate to */\n localeTo: string;\n req: PayloadRequest;\n texts: string[];\n};\n\nexport type TranslateResolverResponse =\n | {\n success: false;\n }\n | {\n success: true;\n translatedTexts: string[];\n };\n\nexport type TranslateResolver = {\n key: string;\n resolve: (\n args: TranslateResolverArgs,\n ) => Promise<TranslateResolverResponse> | TranslateResolverResponse;\n};\n"],"names":[],"mappings":"AAoBA,
|
|
1
|
+
{"version":3,"sources":["../../src/resolvers/types.ts"],"sourcesContent":["import type { PayloadRequest } from 'payload';\n\nexport type TranslateResolverArgs = {\n /** Locale to translate from */\n localeFrom: string;\n /** Locale to translate to */\n localeTo: string;\n req: PayloadRequest;\n texts: string[];\n};\n\nexport type TranslateResolverResponse =\n | {\n success: false;\n }\n | {\n success: true;\n translatedTexts: string[];\n };\n\nexport type TranslateResolver = {\n glossary?: {\n sync: (req: PayloadRequest, entry?: Record<string, string>) => Promise<void>;\n };\n key: string;\n resolve: (\n args: TranslateResolverArgs,\n ) => Promise<TranslateResolverResponse> | TranslateResolverResponse;\n};\n"],"names":[],"mappings":"AAoBA,WAQE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"endpoint.d.ts","sourceRoot":"","sources":["../../src/translate/endpoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"endpoint.d.ts","sourceRoot":"","sources":["../../src/translate/endpoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAO9C,eAAO,MAAM,iBAAiB,EAAE,cAsB/B,CAAC"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { APIError } from 'payload';
|
|
2
|
+
import { translatorT } from '../i18n-translations';
|
|
2
3
|
import { translateOperation } from './operation';
|
|
3
4
|
export const translateEndpoint = async (req)=>{
|
|
4
|
-
if (!req.json) throw new APIError(
|
|
5
|
+
if (!req.json) throw new APIError(translatorT(req.t, 'error_jsonRequired'));
|
|
5
6
|
const args = await req.json();
|
|
6
7
|
const { collectionSlug, data, emptyOnly, globalSlug, id, locale, localeFrom, resolver } = args;
|
|
7
8
|
const result = await translateOperation({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/translate/endpoint.ts"],"sourcesContent":["import type { PayloadHandler } from 'payload';\nimport { APIError } from 'payload';\n\nimport { translateOperation } from './operation';\nimport type { TranslateEndpointArgs } from './types';\n\nexport const translateEndpoint: PayloadHandler = async (req) => {\n if (!req.json) throw new APIError(
|
|
1
|
+
{"version":3,"sources":["../../src/translate/endpoint.ts"],"sourcesContent":["import type { PayloadHandler } from 'payload';\nimport { APIError } from 'payload';\n\nimport { translatorT } from '../i18n-translations';\nimport { translateOperation } from './operation';\nimport type { TranslateEndpointArgs } from './types';\n\nexport const translateEndpoint: PayloadHandler = async (req) => {\n if (!req.json) throw new APIError(translatorT(req.t, 'error_jsonRequired'));\n\n const args: TranslateEndpointArgs = await req.json();\n\n const { collectionSlug, data, emptyOnly, globalSlug, id, locale, localeFrom, resolver } = args;\n\n const result = await translateOperation({\n collectionSlug,\n data,\n emptyOnly,\n globalSlug,\n id,\n locale,\n localeFrom,\n overrideAccess: false,\n req,\n resolver,\n update: false,\n });\n\n return Response.json(result);\n};\n"],"names":["APIError","translatorT","translateOperation","translateEndpoint","req","json","t","args","collectionSlug","data","emptyOnly","globalSlug","id","locale","localeFrom","resolver","result","overrideAccess","update","Response"],"mappings":"AACA,SAASA,QAAQ,QAAQ,UAAU;AAEnC,SAASC,WAAW,QAAQ,uBAAuB;AACnD,SAASC,kBAAkB,QAAQ,cAAc;AAGjD,OAAO,MAAMC,oBAAoC,OAAOC;IACtD,IAAI,CAACA,IAAIC,IAAI,EAAE,MAAM,IAAIL,SAASC,YAAYG,IAAIE,CAAC,EAAE;IAErD,MAAMC,OAA8B,MAAMH,IAAIC,IAAI;IAElD,MAAM,EAAEG,cAAc,EAAEC,IAAI,EAAEC,SAAS,EAAEC,UAAU,EAAEC,EAAE,EAAEC,MAAM,EAAEC,UAAU,EAAEC,QAAQ,EAAE,GAAGR;IAE1F,MAAMS,SAAS,MAAMd,mBAAmB;QACtCM;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAG,gBAAgB;QAChBb;QACAW;QACAG,QAAQ;IACV;IAEA,OAAOC,SAASd,IAAI,CAACW;AACvB,EAAE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"findEntityWithConfig.d.ts","sourceRoot":"","sources":["../../src/translate/findEntityWithConfig.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"findEntityWithConfig.d.ts","sourceRoot":"","sources":["../../src/translate/findEntityWithConfig.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAGV,cAAc,EACd,yBAAyB,EACzB,qBAAqB,EACrB,UAAU,EACX,MAAM,SAAS,CAAC;AAGjB,KAAK,IAAI,GAAG;IACV,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,GAAG,EAAE,cAAc,CAAC;CACrB,CAAC;AAOF,eAAO,MAAM,oBAAoB,SACzB,IAAI,KACT,OAAO,CAAC;IACT,MAAM,EAAE,yBAAyB,GAAG,qBAAqB,CAAC;IAC1D,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,CAAC;CAC3C,CA4CA,CAAC"}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
import { translatorT } from '../i18n-translations';
|
|
1
2
|
import { APIError } from 'payload';
|
|
2
3
|
const findConfigBySlug = (slug, enities)=>enities.find((entity)=>entity.slug === slug);
|
|
3
4
|
export const findEntityWithConfig = async (args)=>{
|
|
4
5
|
const { collectionSlug, globalSlug, id, locale, overrideAccess, req } = args;
|
|
5
|
-
if (!collectionSlug && !globalSlug) throw new APIError(
|
|
6
|
+
if (!collectionSlug && !globalSlug) throw new APIError(translatorT(req.t, 'error_badRequest'), 400);
|
|
6
7
|
const { payload } = req;
|
|
7
8
|
const { config } = payload;
|
|
8
9
|
const isGlobal = !!globalSlug;
|
|
9
|
-
if (!isGlobal && !id) throw new APIError(
|
|
10
|
+
if (!isGlobal && !id) throw new APIError(translatorT(req.t, 'error_badRequest'), 400);
|
|
10
11
|
const entityConfig = isGlobal ? findConfigBySlug(globalSlug, config.globals) : findConfigBySlug(collectionSlug, config.collections);
|
|
11
|
-
if (!entityConfig) throw new APIError(
|
|
12
|
+
if (!entityConfig) throw new APIError(translatorT(req.t, 'error_badRequest'), 400);
|
|
12
13
|
const docPromise = isGlobal ? payload.findGlobal({
|
|
13
14
|
depth: 0,
|
|
14
15
|
fallbackLocale: undefined,
|
|
@@ -19,12 +20,12 @@ export const findEntityWithConfig = async (args)=>{
|
|
|
19
20
|
}) : payload.findByID({
|
|
20
21
|
collection: collectionSlug,
|
|
21
22
|
depth: 0,
|
|
23
|
+
draft: true,
|
|
22
24
|
fallbackLocale: undefined,
|
|
23
25
|
id: id,
|
|
24
26
|
locale: locale,
|
|
25
27
|
overrideAccess,
|
|
26
|
-
req
|
|
27
|
-
draft: true
|
|
28
|
+
req
|
|
28
29
|
});
|
|
29
30
|
return {
|
|
30
31
|
config: entityConfig,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/translate/findEntityWithConfig.ts"],"sourcesContent":["import type {\n CollectionSlug,\n GlobalSlug,\n PayloadRequest,\n SanitizedCollectionConfig,\n SanitizedGlobalConfig,\n TypeWithID,\n} from 'payload';\nimport { APIError } from 'payload';\n\ntype Args = {\n collectionSlug?: string;\n globalSlug?: string;\n id?: number | string;\n locale: string;\n overrideAccess?: boolean;\n req: PayloadRequest;\n};\n\nconst findConfigBySlug = (\n slug: string,\n enities: SanitizedCollectionConfig[] | SanitizedGlobalConfig[],\n) => enities.find((entity) => entity.slug === slug);\n\nexport const findEntityWithConfig = async (\n args: Args,\n): Promise<{\n config: SanitizedCollectionConfig | SanitizedGlobalConfig;\n doc: Record<string, unknown> & TypeWithID;\n}> => {\n const { collectionSlug, globalSlug, id, locale, overrideAccess, req } = args;\n\n if (!collectionSlug && !globalSlug)
|
|
1
|
+
{"version":3,"sources":["../../src/translate/findEntityWithConfig.ts"],"sourcesContent":["import { translatorT } from '../i18n-translations';\nimport type {\n CollectionSlug,\n GlobalSlug,\n PayloadRequest,\n SanitizedCollectionConfig,\n SanitizedGlobalConfig,\n TypeWithID,\n} from 'payload';\nimport { APIError } from 'payload';\n\ntype Args = {\n collectionSlug?: string;\n globalSlug?: string;\n id?: number | string;\n locale: string;\n overrideAccess?: boolean;\n req: PayloadRequest;\n};\n\nconst findConfigBySlug = (\n slug: string,\n enities: SanitizedCollectionConfig[] | SanitizedGlobalConfig[],\n) => enities.find((entity) => entity.slug === slug);\n\nexport const findEntityWithConfig = async (\n args: Args,\n): Promise<{\n config: SanitizedCollectionConfig | SanitizedGlobalConfig;\n doc: Record<string, unknown> & TypeWithID;\n}> => {\n const { collectionSlug, globalSlug, id, locale, overrideAccess, req } = args;\n\n if (!collectionSlug && !globalSlug)\n throw new APIError(translatorT(req.t, 'error_badRequest'), 400);\n\n const { payload } = req;\n\n const { config } = payload;\n\n const isGlobal = !!globalSlug;\n\n if (!isGlobal && !id) throw new APIError(translatorT(req.t, 'error_badRequest'), 400);\n\n const entityConfig = isGlobal\n ? findConfigBySlug(globalSlug, config.globals)\n : findConfigBySlug(collectionSlug as string, config.collections);\n\n if (!entityConfig) throw new APIError(translatorT(req.t, 'error_badRequest'), 400);\n\n const docPromise = isGlobal\n ? payload.findGlobal({\n depth: 0,\n fallbackLocale: undefined,\n locale: locale as any,\n overrideAccess,\n req,\n slug: args.globalSlug as GlobalSlug,\n })\n : payload.findByID({\n collection: collectionSlug as CollectionSlug,\n depth: 0,\n draft: true,\n fallbackLocale: undefined,\n id: id as number | string,\n locale: locale as any,\n overrideAccess,\n req,\n });\n\n return {\n config: entityConfig,\n doc: (await docPromise) as any,\n };\n};\n"],"names":["translatorT","APIError","findConfigBySlug","slug","enities","find","entity","findEntityWithConfig","args","collectionSlug","globalSlug","id","locale","overrideAccess","req","t","payload","config","isGlobal","entityConfig","globals","collections","docPromise","findGlobal","depth","fallbackLocale","undefined","findByID","collection","draft","doc"],"mappings":"AAAA,SAASA,WAAW,QAAQ,uBAAuB;AASnD,SAASC,QAAQ,QAAQ,UAAU;AAWnC,MAAMC,mBAAmB,CACvBC,MACAC,UACGA,QAAQC,IAAI,CAAC,CAACC,SAAWA,OAAOH,IAAI,KAAKA;AAE9C,OAAO,MAAMI,uBAAuB,OAClCC;IAKA,MAAM,EAAEC,cAAc,EAAEC,UAAU,EAAEC,EAAE,EAAEC,MAAM,EAAEC,cAAc,EAAEC,GAAG,EAAE,GAAGN;IAExE,IAAI,CAACC,kBAAkB,CAACC,YACtB,MAAM,IAAIT,SAASD,YAAYc,IAAIC,CAAC,EAAE,qBAAqB;IAE7D,MAAM,EAAEC,OAAO,EAAE,GAAGF;IAEpB,MAAM,EAAEG,MAAM,EAAE,GAAGD;IAEnB,MAAME,WAAW,CAAC,CAACR;IAEnB,IAAI,CAACQ,YAAY,CAACP,IAAI,MAAM,IAAIV,SAASD,YAAYc,IAAIC,CAAC,EAAE,qBAAqB;IAEjF,MAAMI,eAAeD,WACjBhB,iBAAiBQ,YAAYO,OAAOG,OAAO,IAC3ClB,iBAAiBO,gBAA0BQ,OAAOI,WAAW;IAEjE,IAAI,CAACF,cAAc,MAAM,IAAIlB,SAASD,YAAYc,IAAIC,CAAC,EAAE,qBAAqB;IAE9E,MAAMO,aAAaJ,WACfF,QAAQO,UAAU,CAAC;QACjBC,OAAO;QACPC,gBAAgBC;QAChBd,QAAQA;QACRC;QACAC;QACAX,MAAMK,KAAKE,UAAU;IACvB,KACAM,QAAQW,QAAQ,CAAC;QACfC,YAAYnB;QACZe,OAAO;QACPK,OAAO;QACPJ,gBAAgBC;QAChBf,IAAIA;QACJC,QAAQA;QACRC;QACAC;IACF;IAEJ,OAAO;QACLG,QAAQE;QACRW,KAAM,MAAMR;IACd;AACF,EAAE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operation.d.ts","sourceRoot":"","sources":["../../src/translate/operation.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,KAAK,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"operation.d.ts","sourceRoot":"","sources":["../../src/translate/operation.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,KAAK,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,SAAS,CAAC;AAMtE,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAoB,MAAM,SAAS,CAAC;AAGhF,MAAM,MAAM,sBAAsB,GAAG,CACjC;IACE,OAAO,EAAE,OAAO,CAAC;CAClB,GACD;IACE,GAAG,EAAE,cAAc,CAAC;CACrB,CACJ,GACC,aAAa,CAAC;AAEhB,eAAO,MAAM,kBAAkB,SAAgB,sBAAsB,6BA2FpE,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import he from 'he';
|
|
2
2
|
import { APIError } from 'payload';
|
|
3
|
+
import { translatorT } from '../i18n-translations';
|
|
3
4
|
import { findEntityWithConfig } from './findEntityWithConfig';
|
|
4
5
|
import { traverseFields } from './traverseFields';
|
|
5
6
|
import { updateEntity } from './updateEntity';
|
|
@@ -13,10 +14,13 @@ export const translateOperation = async (args)=>{
|
|
|
13
14
|
globalSlug,
|
|
14
15
|
id,
|
|
15
16
|
locale: localeFrom,
|
|
17
|
+
overrideAccess,
|
|
16
18
|
req
|
|
17
19
|
});
|
|
18
20
|
const resolver = (req.payload.config.custom?.translator?.resolvers ?? []).find((each)=>each.key === args.resolver);
|
|
19
|
-
if (!resolver) throw new APIError(
|
|
21
|
+
if (!resolver) throw new APIError(translatorT(req.t, 'error_missingResolver', {
|
|
22
|
+
resolver: args.resolver
|
|
23
|
+
}));
|
|
20
24
|
const valuesToTranslate = [];
|
|
21
25
|
let translatedData = args.data;
|
|
22
26
|
if (!translatedData) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/translate/operation.ts"],"sourcesContent":["import he from 'he';\nimport { APIError, type Payload, type PayloadRequest } from 'payload';\n\nimport type { TranslateResolver } from '../resolvers/types';\nimport { findEntityWithConfig } from './findEntityWithConfig';\nimport { traverseFields } from './traverseFields';\nimport type { TranslateArgs, TranslateResult, ValueToTranslate } from './types';\nimport { updateEntity } from './updateEntity';\n\nexport type TranslateOperationArgs = (\n | {\n payload: Payload;\n }\n | {\n req: PayloadRequest;\n }\n) &\n TranslateArgs;\n\nexport const translateOperation = async (args: TranslateOperationArgs) => {\n const req: PayloadRequest =\n 'req' in args\n ? args.req\n : ({\n payload: args.payload,\n } as PayloadRequest);\n\n const { collectionSlug, globalSlug, id, locale, localeFrom, overrideAccess } = args;\n\n const { config, doc: dataFrom } = await findEntityWithConfig({\n collectionSlug,\n globalSlug,\n id,\n locale: localeFrom,\n req,\n });\n\n const resolver = (\n (req.payload.config.custom?.translator?.resolvers as TranslateResolver[]) ?? []\n ).find((each) => each.key === args.resolver);\n\n if (!resolver)
|
|
1
|
+
{"version":3,"sources":["../../src/translate/operation.ts"],"sourcesContent":["import he from 'he';\nimport { APIError, type Payload, type PayloadRequest } from 'payload';\n\nimport { translatorT } from '../i18n-translations';\nimport type { TranslateResolver } from '../resolvers/types';\nimport { findEntityWithConfig } from './findEntityWithConfig';\nimport { traverseFields } from './traverseFields';\nimport type { TranslateArgs, TranslateResult, ValueToTranslate } from './types';\nimport { updateEntity } from './updateEntity';\n\nexport type TranslateOperationArgs = (\n | {\n payload: Payload;\n }\n | {\n req: PayloadRequest;\n }\n) &\n TranslateArgs;\n\nexport const translateOperation = async (args: TranslateOperationArgs) => {\n const req: PayloadRequest =\n 'req' in args\n ? args.req\n : ({\n payload: args.payload,\n } as PayloadRequest);\n\n const { collectionSlug, globalSlug, id, locale, localeFrom, overrideAccess } = args;\n\n const { config, doc: dataFrom } = await findEntityWithConfig({\n collectionSlug,\n globalSlug,\n id,\n locale: localeFrom,\n overrideAccess,\n req,\n });\n\n const resolver = (\n (req.payload.config.custom?.translator?.resolvers as TranslateResolver[]) ?? []\n ).find((each) => each.key === args.resolver);\n\n if (!resolver)\n throw new APIError(translatorT(req.t, 'error_missingResolver', { resolver: args.resolver }));\n\n const valuesToTranslate: ValueToTranslate[] = [];\n\n let translatedData = args.data;\n\n if (!translatedData) {\n const { doc } = await findEntityWithConfig({\n collectionSlug,\n globalSlug,\n id,\n locale,\n overrideAccess,\n req,\n });\n\n translatedData = doc;\n }\n\n traverseFields({\n dataFrom,\n emptyOnly: args.emptyOnly,\n fields: config.fields,\n translatedData,\n valuesToTranslate,\n });\n\n const resolveResult = await resolver.resolve({\n localeFrom: args.localeFrom,\n localeTo: args.locale,\n req,\n texts: valuesToTranslate.map((each) => each.value),\n });\n\n let result: TranslateResult;\n\n if (!resolveResult.success) {\n result = {\n success: false,\n };\n } else {\n resolveResult.translatedTexts.forEach((translated, index) => {\n const formattedValue = he.decode(translated);\n\n valuesToTranslate[index].onTranslate(formattedValue);\n });\n\n if (args.update) {\n await updateEntity({\n collectionSlug,\n data: translatedData,\n depth: 0,\n globalSlug,\n id,\n locale,\n overrideAccess,\n req,\n });\n }\n\n result = {\n success: true,\n translatedData,\n };\n }\n\n return result;\n};\n"],"names":["he","APIError","translatorT","findEntityWithConfig","traverseFields","updateEntity","translateOperation","args","req","payload","collectionSlug","globalSlug","id","locale","localeFrom","overrideAccess","config","doc","dataFrom","resolver","custom","translator","resolvers","find","each","key","t","valuesToTranslate","translatedData","data","emptyOnly","fields","resolveResult","resolve","localeTo","texts","map","value","result","success","translatedTexts","forEach","translated","index","formattedValue","decode","onTranslate","update","depth"],"mappings":"AAAA,OAAOA,QAAQ,KAAK;AACpB,SAASC,QAAQ,QAA2C,UAAU;AAEtE,SAASC,WAAW,QAAQ,uBAAuB;AAEnD,SAASC,oBAAoB,QAAQ,yBAAyB;AAC9D,SAASC,cAAc,QAAQ,mBAAmB;AAElD,SAASC,YAAY,QAAQ,iBAAiB;AAY9C,OAAO,MAAMC,qBAAqB,OAAOC;IACvC,MAAMC,MACJ,SAASD,OACLA,KAAKC,GAAG,GACP;QACCC,SAASF,KAAKE,OAAO;IACvB;IAEN,MAAM,EAAEC,cAAc,EAAEC,UAAU,EAAEC,EAAE,EAAEC,MAAM,EAAEC,UAAU,EAAEC,cAAc,EAAE,GAAGR;IAE/E,MAAM,EAAES,MAAM,EAAEC,KAAKC,QAAQ,EAAE,GAAG,MAAMf,qBAAqB;QAC3DO;QACAC;QACAC;QACAC,QAAQC;QACRC;QACAP;IACF;IAEA,MAAMW,WAAW,AACf,CAAA,AAACX,IAAIC,OAAO,CAACO,MAAM,CAACI,MAAM,EAAEC,YAAYC,aAAqC,EAAE,AAAD,EAC9EC,IAAI,CAAC,CAACC,OAASA,KAAKC,GAAG,KAAKlB,KAAKY,QAAQ;IAE3C,IAAI,CAACA,UACH,MAAM,IAAIlB,SAASC,YAAYM,IAAIkB,CAAC,EAAE,yBAAyB;QAAEP,UAAUZ,KAAKY,QAAQ;IAAC;IAE3F,MAAMQ,oBAAwC,EAAE;IAEhD,IAAIC,iBAAiBrB,KAAKsB,IAAI;IAE9B,IAAI,CAACD,gBAAgB;QACnB,MAAM,EAAEX,GAAG,EAAE,GAAG,MAAMd,qBAAqB;YACzCO;YACAC;YACAC;YACAC;YACAE;YACAP;QACF;QAEAoB,iBAAiBX;IACnB;IAEAb,eAAe;QACbc;QACAY,WAAWvB,KAAKuB,SAAS;QACzBC,QAAQf,OAAOe,MAAM;QACrBH;QACAD;IACF;IAEA,MAAMK,gBAAgB,MAAMb,SAASc,OAAO,CAAC;QAC3CnB,YAAYP,KAAKO,UAAU;QAC3BoB,UAAU3B,KAAKM,MAAM;QACrBL;QACA2B,OAAOR,kBAAkBS,GAAG,CAAC,CAACZ,OAASA,KAAKa,KAAK;IACnD;IAEA,IAAIC;IAEJ,IAAI,CAACN,cAAcO,OAAO,EAAE;QAC1BD,SAAS;YACPC,SAAS;QACX;IACF,OAAO;QACLP,cAAcQ,eAAe,CAACC,OAAO,CAAC,CAACC,YAAYC;YACjD,MAAMC,iBAAiB5C,GAAG6C,MAAM,CAACH;YAEjCf,iBAAiB,CAACgB,MAAM,CAACG,WAAW,CAACF;QACvC;QAEA,IAAIrC,KAAKwC,MAAM,EAAE;YACf,MAAM1C,aAAa;gBACjBK;gBACAmB,MAAMD;gBACNoB,OAAO;gBACPrC;gBACAC;gBACAC;gBACAE;gBACAP;YACF;QACF;QAEA8B,SAAS;YACPC,SAAS;YACTX;QACF;IACF;IAEA,OAAOU;AACT,EAAE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"traverseFields.d.ts","sourceRoot":"","sources":["../../src/translate/traverseFields.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAKrC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD,eAAO,MAAM,cAAc,iIASxB;IACD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,qBAAqB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChD,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;CACvC,
|
|
1
|
+
{"version":3,"file":"traverseFields.d.ts","sourceRoot":"","sources":["../../src/translate/traverseFields.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAKrC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD,eAAO,MAAM,cAAc,iIASxB;IACD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,qBAAqB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChD,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;CACvC,SAkTA,CAAC"}
|
|
@@ -6,6 +6,7 @@ export const traverseFields = ({ dataFrom, emptyOnly, fields, localizedParent, s
|
|
|
6
6
|
siblingDataFrom = siblingDataFrom ?? dataFrom;
|
|
7
7
|
siblingDataTranslated = siblingDataTranslated ?? translatedData;
|
|
8
8
|
for (const field of fields){
|
|
9
|
+
if (field.custom && typeof field.custom === 'object' && field.custom.translatorSkip) continue;
|
|
9
10
|
switch(field.type){
|
|
10
11
|
case 'tabs':
|
|
11
12
|
for (const tab of field.tabs){
|
|
@@ -27,6 +28,20 @@ export const traverseFields = ({ dataFrom, emptyOnly, fields, localizedParent, s
|
|
|
27
28
|
break;
|
|
28
29
|
case 'group':
|
|
29
30
|
{
|
|
31
|
+
const groupFields = field.fields;
|
|
32
|
+
if (!('name' in field)) {
|
|
33
|
+
traverseFields({
|
|
34
|
+
dataFrom,
|
|
35
|
+
emptyOnly,
|
|
36
|
+
fields: groupFields,
|
|
37
|
+
localizedParent,
|
|
38
|
+
siblingDataFrom,
|
|
39
|
+
siblingDataTranslated,
|
|
40
|
+
translatedData,
|
|
41
|
+
valuesToTranslate
|
|
42
|
+
});
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
30
45
|
const groupDataFrom = siblingDataFrom[field.name];
|
|
31
46
|
if (!groupDataFrom) break;
|
|
32
47
|
let groupDataTranslated = siblingDataTranslated[field.name];
|
|
@@ -131,11 +146,11 @@ export const traverseFields = ({ dataFrom, emptyOnly, fields, localizedParent, s
|
|
|
131
146
|
case 'relationship':
|
|
132
147
|
case 'select':
|
|
133
148
|
case 'upload':
|
|
149
|
+
if (emptyOnly && !isEmpty(siblingDataTranslated[field.name]) && siblingDataTranslated[field.name] !== '') break;
|
|
134
150
|
siblingDataTranslated[field.name] = siblingDataFrom[field.name];
|
|
135
151
|
break;
|
|
136
152
|
case 'text':
|
|
137
153
|
case 'textarea':
|
|
138
|
-
if (field.custom && typeof field.custom === 'object' && field.custom.translatorSkip) break;
|
|
139
154
|
if (!(field.localized || localizedParent) || isEmpty(siblingDataFrom[field.name])) break;
|
|
140
155
|
if (emptyOnly && siblingDataTranslated[field.name]) break;
|
|
141
156
|
// do not translate the block ID or admin-facing label
|