@pigment/auto-translate 1.3.0 → 1.3.2

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.
Files changed (31) hide show
  1. package/README.md +27 -0
  2. package/dist/collections/translationExclusions.js +4 -4
  3. package/dist/collections/translationExclusions.js.map +1 -1
  4. package/dist/components/LockTranslation/actions/lockTranslations.d.ts +8 -0
  5. package/dist/components/LockTranslation/actions/lockTranslations.js +33 -0
  6. package/dist/components/LockTranslation/actions/lockTranslations.js.map +1 -0
  7. package/dist/components/LockTranslation/index.d.ts +10 -0
  8. package/dist/components/LockTranslation/index.js +98 -0
  9. package/dist/components/LockTranslation/index.js.map +1 -0
  10. package/dist/components/LockTranslation/style.css +87 -0
  11. package/dist/components/TranslationSettingsLock.css +87 -0
  12. package/dist/components/TranslationSettingsLock.d.ts +9 -0
  13. package/dist/components/TranslationSettingsLock.js +155 -0
  14. package/dist/components/TranslationSettingsLock.js.map +1 -0
  15. package/dist/exports/client.d.ts +1 -3
  16. package/dist/exports/client.js +2 -3
  17. package/dist/exports/client.js.map +1 -1
  18. package/dist/exports/rsc.d.ts +1 -0
  19. package/dist/exports/rsc.js +1 -0
  20. package/dist/exports/rsc.js.map +1 -1
  21. package/dist/globals/translationSettings.js +73 -8
  22. package/dist/globals/translationSettings.js.map +1 -1
  23. package/dist/index.d.ts +1 -0
  24. package/dist/index.js +42 -26
  25. package/dist/index.js.map +1 -1
  26. package/dist/services/translationService.d.ts +5 -4
  27. package/dist/services/translationService.js +118 -117
  28. package/dist/services/translationService.js.map +1 -1
  29. package/dist/types/index.d.ts +1 -1
  30. package/dist/types/index.js.map +1 -1
  31. package/package.json +9 -9
@@ -2,4 +2,5 @@
2
2
  * React Server Component exports for the auto-translate plugin
3
3
  */
4
4
  export { getTranslationSettingsGlobal } from '../globals/translationSettings.js';
5
+ export { TranslationService } from '../services/translationService.js';
5
6
  export type * from '../types/index.js';
@@ -1,5 +1,6 @@
1
1
  /**
2
2
  * React Server Component exports for the auto-translate plugin
3
3
  */ export { getTranslationSettingsGlobal } from '../globals/translationSettings.js';
4
+ export { TranslationService } from '../services/translationService.js';
4
5
 
5
6
  //# sourceMappingURL=rsc.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/exports/rsc.ts"],"sourcesContent":["/**\n * React Server Component exports for the auto-translate plugin\n */\n\nexport { getTranslationSettingsGlobal } from '../globals/translationSettings.js'\nexport type * from '../types/index.js'\n"],"names":["getTranslationSettingsGlobal"],"mappings":"AAAA;;CAEC,GAED,SAASA,4BAA4B,QAAQ,oCAAmC"}
1
+ {"version":3,"sources":["../../src/exports/rsc.ts"],"sourcesContent":["/**\n * React Server Component exports for the auto-translate plugin\n */\n\nexport { getTranslationSettingsGlobal } from '../globals/translationSettings.js'\nexport { TranslationService } from '../services/translationService.js'\nexport type * from '../types/index.js'\n"],"names":["getTranslationSettingsGlobal","TranslationService"],"mappings":"AAAA;;CAEC,GAED,SAASA,4BAA4B,QAAQ,oCAAmC;AAChF,SAASC,kBAAkB,QAAQ,oCAAmC"}
@@ -2,18 +2,43 @@ export const getTranslationSettingsGlobal = (slug = 'translation-settings')=>({
2
2
  slug,
3
3
  access: {
4
4
  read: ()=>true,
5
- update: ({ req })=>{
5
+ update: ()=>{
6
6
  // Only admins can update translation settings
7
- return Boolean(req.user);
7
+ return true;
8
8
  }
9
9
  },
10
10
  admin: {
11
11
  description: 'Configure translation settings including the system prompt and model parameters'
12
12
  },
13
13
  fields: [
14
+ {
15
+ name: 'settingsLock',
16
+ type: 'ui',
17
+ admin: {
18
+ components: {
19
+ Field: '@pigment/auto-translate/client#LockTranslation'
20
+ },
21
+ position: 'sidebar'
22
+ },
23
+ custom: {}
24
+ },
25
+ {
26
+ name: 'lockTranslationSettings',
27
+ type: 'checkbox',
28
+ admin: {
29
+ hidden: true
30
+ },
31
+ defaultValue: true
32
+ },
14
33
  {
15
34
  name: 'systemPrompt',
16
35
  type: 'textarea',
36
+ access: {
37
+ read: ()=>true,
38
+ update: ({ data })=>{
39
+ return !data?.lockTranslationSettings;
40
+ }
41
+ },
17
42
  admin: {
18
43
  description: 'The main instruction for the AI translator. Use {fromLocale} and {toLocale} as placeholders.',
19
44
  rows: 3
@@ -25,23 +50,35 @@ export const getTranslationSettingsGlobal = (slug = 'translation-settings')=>({
25
50
  {
26
51
  name: 'translationRules',
27
52
  type: 'textarea',
53
+ access: {
54
+ read: ()=>true,
55
+ update: ({ data })=>{
56
+ return !data?.lockTranslationSettings;
57
+ }
58
+ },
28
59
  admin: {
29
60
  description: "⚠️ Do not edit if you don't know what you are doing. These rules ensure proper JSON translation behavior.",
30
61
  rows: 8
31
62
  },
32
63
  defaultValue: `Rules:
33
- - Only translate the values, never the keys
34
- - Preserve the exact JSON structure
35
- - Do not translate field names like 'id', 'createdAt', 'updatedAt', etc.
36
- - Maintain formatting, HTML tags, and special characters
37
- - Return only valid JSON without any markdown formatting or code blocks
38
- - If a value is already in the target language or is a proper noun, keep it as is`,
64
+ - Only translate the values, never the keys
65
+ - Preserve the exact JSON structure
66
+ - Do not translate field names like 'id', 'createdAt', 'updatedAt', etc.
67
+ - Maintain formatting, HTML tags, and special characters
68
+ - Return only valid JSON without any markdown formatting or code blocks
69
+ - If a value is already in the target language or is a proper noun, keep it as is`,
39
70
  label: 'Translation Rules',
40
71
  required: true
41
72
  },
42
73
  {
43
74
  name: 'model',
44
75
  type: 'text',
76
+ access: {
77
+ read: ()=>true,
78
+ update: ({ data })=>{
79
+ return !data?.lockTranslationSettings;
80
+ }
81
+ },
45
82
  admin: {
46
83
  description: 'The OpenAI model to use for translations (e.g., gpt-4o, gpt-4o-mini)'
47
84
  },
@@ -52,6 +89,12 @@ export const getTranslationSettingsGlobal = (slug = 'translation-settings')=>({
52
89
  {
53
90
  name: 'temperature',
54
91
  type: 'number',
92
+ access: {
93
+ read: ()=>true,
94
+ update: ({ data })=>{
95
+ return !data?.lockTranslationSettings;
96
+ }
97
+ },
55
98
  admin: {
56
99
  description: 'Controls randomness in translation (0.0-2.0). Lower values are more deterministic.',
57
100
  step: 0.1
@@ -65,6 +108,12 @@ export const getTranslationSettingsGlobal = (slug = 'translation-settings')=>({
65
108
  {
66
109
  name: 'maxTokens',
67
110
  type: 'number',
111
+ access: {
112
+ read: ()=>true,
113
+ update: ({ data })=>{
114
+ return !data?.lockTranslationSettings;
115
+ }
116
+ },
68
117
  admin: {
69
118
  description: 'Maximum tokens for the response. Leave empty for automatic.'
70
119
  },
@@ -72,6 +121,22 @@ export const getTranslationSettingsGlobal = (slug = 'translation-settings')=>({
72
121
  min: 1
73
122
  }
74
123
  ],
124
+ hooks: {
125
+ afterChange: [
126
+ async ({ data, req })=>{
127
+ if (!data?.lockTranslationSettings) {
128
+ const result = await req.payload.updateGlobal({
129
+ slug: 'translation-settings',
130
+ data: {
131
+ lockTranslationSettings: true
132
+ },
133
+ req
134
+ });
135
+ return result;
136
+ }
137
+ }
138
+ ]
139
+ },
75
140
  label: 'Translation Settings'
76
141
  });
77
142
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/globals/translationSettings.ts"],"sourcesContent":["import type { GlobalConfig } from 'payload'\n\nexport const getTranslationSettingsGlobal = (\n slug: string = 'translation-settings',\n): GlobalConfig => ({\n slug,\n access: {\n read: () => true,\n update: ({ req }) => {\n // Only admins can update translation settings\n return Boolean(req.user)\n },\n },\n admin: {\n description: 'Configure translation settings including the system prompt and model parameters',\n },\n fields: [\n {\n name: 'systemPrompt',\n type: 'textarea',\n admin: {\n description:\n 'The main instruction for the AI translator. Use {fromLocale} and {toLocale} as placeholders.',\n rows: 3,\n },\n defaultValue: `You are a professional translator. Translate the JSON object values from {fromLocale} to {toLocale}.`,\n label: 'System Prompt',\n required: true,\n },\n {\n name: 'translationRules',\n type: 'textarea',\n admin: {\n description:\n \"⚠️ Do not edit if you don't know what you are doing. These rules ensure proper JSON translation behavior.\",\n rows: 8,\n },\n defaultValue: `Rules:\n- Only translate the values, never the keys\n- Preserve the exact JSON structure\n- Do not translate field names like 'id', 'createdAt', 'updatedAt', etc.\n- Maintain formatting, HTML tags, and special characters\n- Return only valid JSON without any markdown formatting or code blocks\n- If a value is already in the target language or is a proper noun, keep it as is`,\n label: 'Translation Rules',\n required: true,\n },\n {\n name: 'model',\n type: 'text',\n admin: {\n description: 'The OpenAI model to use for translations (e.g., gpt-4o, gpt-4o-mini)',\n },\n defaultValue: 'gpt-4o',\n label: 'Model',\n required: true,\n },\n {\n name: 'temperature',\n type: 'number',\n admin: {\n description:\n 'Controls randomness in translation (0.0-2.0). Lower values are more deterministic.',\n step: 0.1,\n },\n defaultValue: 0.3,\n label: 'Temperature',\n max: 2,\n min: 0,\n required: true,\n },\n {\n name: 'maxTokens',\n type: 'number',\n admin: {\n description: 'Maximum tokens for the response. Leave empty for automatic.',\n },\n label: 'Max Tokens',\n min: 1,\n },\n ],\n label: 'Translation Settings',\n})\n"],"names":["getTranslationSettingsGlobal","slug","access","read","update","req","Boolean","user","admin","description","fields","name","type","rows","defaultValue","label","required","step","max","min"],"mappings":"AAEA,OAAO,MAAMA,+BAA+B,CAC1CC,OAAe,sBAAsB,GACnB,CAAA;QAClBA;QACAC,QAAQ;YACNC,MAAM,IAAM;YACZC,QAAQ,CAAC,EAAEC,GAAG,EAAE;gBACd,8CAA8C;gBAC9C,OAAOC,QAAQD,IAAIE,IAAI;YACzB;QACF;QACAC,OAAO;YACLC,aAAa;QACf;QACAC,QAAQ;YACN;gBACEC,MAAM;gBACNC,MAAM;gBACNJ,OAAO;oBACLC,aACE;oBACFI,MAAM;gBACR;gBACAC,cAAc,CAAC,oGAAoG,CAAC;gBACpHC,OAAO;gBACPC,UAAU;YACZ;YACA;gBACEL,MAAM;gBACNC,MAAM;gBACNJ,OAAO;oBACLC,aACE;oBACFI,MAAM;gBACR;gBACAC,cAAc,CAAC;;;;;;iFAM4D,CAAC;gBAC5EC,OAAO;gBACPC,UAAU;YACZ;YACA;gBACEL,MAAM;gBACNC,MAAM;gBACNJ,OAAO;oBACLC,aAAa;gBACf;gBACAK,cAAc;gBACdC,OAAO;gBACPC,UAAU;YACZ;YACA;gBACEL,MAAM;gBACNC,MAAM;gBACNJ,OAAO;oBACLC,aACE;oBACFQ,MAAM;gBACR;gBACAH,cAAc;gBACdC,OAAO;gBACPG,KAAK;gBACLC,KAAK;gBACLH,UAAU;YACZ;YACA;gBACEL,MAAM;gBACNC,MAAM;gBACNJ,OAAO;oBACLC,aAAa;gBACf;gBACAM,OAAO;gBACPI,KAAK;YACP;SACD;QACDJ,OAAO;IACT,CAAA,EAAE"}
1
+ {"version":3,"sources":["../../src/globals/translationSettings.ts"],"sourcesContent":["import type { GlobalConfig } from 'payload'\n\nexport const getTranslationSettingsGlobal = (\n slug: string = 'translation-settings',\n): GlobalConfig => ({\n slug,\n access: {\n read: () => true,\n update: () => {\n // Only admins can update translation settings\n return true\n },\n },\n admin: {\n description: 'Configure translation settings including the system prompt and model parameters',\n },\n fields: [\n {\n name: 'settingsLock',\n type: 'ui',\n admin: {\n components: {\n Field: '@pigment/auto-translate/client#LockTranslation',\n },\n position: 'sidebar',\n },\n custom: {},\n },\n {\n name: 'lockTranslationSettings',\n type: 'checkbox',\n admin: {\n hidden: true,\n },\n defaultValue: true,\n },\n {\n name: 'systemPrompt',\n type: 'textarea',\n access: {\n read: () => true,\n update: ({ data }) => {\n return !data?.lockTranslationSettings\n },\n },\n admin: {\n description:\n 'The main instruction for the AI translator. Use {fromLocale} and {toLocale} as placeholders.',\n rows: 3,\n },\n defaultValue: `You are a professional translator. Translate the JSON object values from {fromLocale} to {toLocale}.`,\n label: 'System Prompt',\n required: true,\n },\n {\n name: 'translationRules',\n type: 'textarea',\n access: {\n read: () => true,\n update: ({ data }) => {\n return !data?.lockTranslationSettings\n },\n },\n admin: {\n description:\n \"⚠️ Do not edit if you don't know what you are doing. These rules ensure proper JSON translation behavior.\",\n rows: 8,\n },\n defaultValue: `Rules:\n - Only translate the values, never the keys\n - Preserve the exact JSON structure\n - Do not translate field names like 'id', 'createdAt', 'updatedAt', etc.\n - Maintain formatting, HTML tags, and special characters\n - Return only valid JSON without any markdown formatting or code blocks\n - If a value is already in the target language or is a proper noun, keep it as is`,\n label: 'Translation Rules',\n required: true,\n },\n {\n name: 'model',\n type: 'text',\n access: {\n read: () => true,\n update: ({ data }) => {\n return !data?.lockTranslationSettings\n },\n },\n admin: {\n description: 'The OpenAI model to use for translations (e.g., gpt-4o, gpt-4o-mini)',\n },\n defaultValue: 'gpt-4o',\n label: 'Model',\n required: true,\n },\n {\n name: 'temperature',\n type: 'number',\n access: {\n read: () => true,\n update: ({ data }) => {\n return !data?.lockTranslationSettings\n },\n },\n admin: {\n description:\n 'Controls randomness in translation (0.0-2.0). Lower values are more deterministic.',\n step: 0.1,\n },\n defaultValue: 0.3,\n label: 'Temperature',\n max: 2,\n min: 0,\n required: true,\n },\n {\n name: 'maxTokens',\n type: 'number',\n access: {\n read: () => true,\n update: ({ data }) => {\n return !data?.lockTranslationSettings\n },\n },\n admin: {\n description: 'Maximum tokens for the response. Leave empty for automatic.',\n },\n label: 'Max Tokens',\n min: 1,\n },\n ],\n hooks: {\n afterChange: [\n async ({ data, req }) => {\n if (!data?.lockTranslationSettings) {\n const result = await req.payload.updateGlobal({\n slug: 'translation-settings',\n data: { lockTranslationSettings: true },\n req,\n })\n\n return result\n }\n },\n ],\n },\n label: 'Translation Settings',\n})\n"],"names":["getTranslationSettingsGlobal","slug","access","read","update","admin","description","fields","name","type","components","Field","position","custom","hidden","defaultValue","data","lockTranslationSettings","rows","label","required","step","max","min","hooks","afterChange","req","result","payload","updateGlobal"],"mappings":"AAEA,OAAO,MAAMA,+BAA+B,CAC1CC,OAAe,sBAAsB,GACnB,CAAA;QAClBA;QACAC,QAAQ;YACNC,MAAM,IAAM;YACZC,QAAQ;gBACN,8CAA8C;gBAC9C,OAAO;YACT;QACF;QACAC,OAAO;YACLC,aAAa;QACf;QACAC,QAAQ;YACN;gBACEC,MAAM;gBACNC,MAAM;gBACNJ,OAAO;oBACLK,YAAY;wBACVC,OAAO;oBACT;oBACAC,UAAU;gBACZ;gBACAC,QAAQ,CAAC;YACX;YACA;gBACEL,MAAM;gBACNC,MAAM;gBACNJ,OAAO;oBACLS,QAAQ;gBACV;gBACAC,cAAc;YAChB;YACA;gBACEP,MAAM;gBACNC,MAAM;gBACNP,QAAQ;oBACNC,MAAM,IAAM;oBACZC,QAAQ,CAAC,EAAEY,IAAI,EAAE;wBACf,OAAO,CAACA,MAAMC;oBAChB;gBACF;gBACAZ,OAAO;oBACLC,aACE;oBACFY,MAAM;gBACR;gBACAH,cAAc,CAAC,oGAAoG,CAAC;gBACpHI,OAAO;gBACPC,UAAU;YACZ;YACA;gBACEZ,MAAM;gBACNC,MAAM;gBACNP,QAAQ;oBACNC,MAAM,IAAM;oBACZC,QAAQ,CAAC,EAAEY,IAAI,EAAE;wBACf,OAAO,CAACA,MAAMC;oBAChB;gBACF;gBACAZ,OAAO;oBACLC,aACE;oBACFY,MAAM;gBACR;gBACAH,cAAc,CAAC;;;;;;qFAMgE,CAAC;gBAChFI,OAAO;gBACPC,UAAU;YACZ;YACA;gBACEZ,MAAM;gBACNC,MAAM;gBACNP,QAAQ;oBACNC,MAAM,IAAM;oBACZC,QAAQ,CAAC,EAAEY,IAAI,EAAE;wBACf,OAAO,CAACA,MAAMC;oBAChB;gBACF;gBACAZ,OAAO;oBACLC,aAAa;gBACf;gBACAS,cAAc;gBACdI,OAAO;gBACPC,UAAU;YACZ;YACA;gBACEZ,MAAM;gBACNC,MAAM;gBACNP,QAAQ;oBACNC,MAAM,IAAM;oBACZC,QAAQ,CAAC,EAAEY,IAAI,EAAE;wBACf,OAAO,CAACA,MAAMC;oBAChB;gBACF;gBACAZ,OAAO;oBACLC,aACE;oBACFe,MAAM;gBACR;gBACAN,cAAc;gBACdI,OAAO;gBACPG,KAAK;gBACLC,KAAK;gBACLH,UAAU;YACZ;YACA;gBACEZ,MAAM;gBACNC,MAAM;gBACNP,QAAQ;oBACNC,MAAM,IAAM;oBACZC,QAAQ,CAAC,EAAEY,IAAI,EAAE;wBACf,OAAO,CAACA,MAAMC;oBAChB;gBACF;gBACAZ,OAAO;oBACLC,aAAa;gBACf;gBACAa,OAAO;gBACPI,KAAK;YACP;SACD;QACDC,OAAO;YACLC,aAAa;gBACX,OAAO,EAAET,IAAI,EAAEU,GAAG,EAAE;oBAClB,IAAI,CAACV,MAAMC,yBAAyB;wBAClC,MAAMU,SAAS,MAAMD,IAAIE,OAAO,CAACC,YAAY,CAAC;4BAC5C5B,MAAM;4BACNe,MAAM;gCAAEC,yBAAyB;4BAAK;4BACtCS;wBACF;wBAEA,OAAOC;oBACT;gBACF;aACD;QACH;QACAR,OAAO;IACT,CAAA,EAAE"}
package/dist/index.d.ts CHANGED
@@ -2,5 +2,6 @@ import type { Config } from 'payload';
2
2
  import type { AutoTranslateConfig } from './types/index.js';
3
3
  export { getTranslationExclusionsCollection } from './collections/translationExclusions.js';
4
4
  export { getTranslationSettingsGlobal } from './globals/translationSettings.js';
5
+ export { TranslationService } from './services/translationService.js';
5
6
  export * from './types/index.js';
6
7
  export declare const autoTranslate: (pluginOptions: AutoTranslateConfig) => (config: Config) => Config;
package/dist/index.js CHANGED
@@ -4,8 +4,16 @@ import { TranslationService } from './services/translationService.js';
4
4
  import { injectTranslationControls } from './utilities/injectTranslationControls.js';
5
5
  export { getTranslationExclusionsCollection } from './collections/translationExclusions.js';
6
6
  export { getTranslationSettingsGlobal } from './globals/translationSettings.js';
7
+ export { TranslationService } from './services/translationService.js';
7
8
  export * from './types/index.js';
8
9
  export const autoTranslate = (pluginOptions)=>(config)=>{
10
+ // If the plugin is disabled, return config immediately without any modifications
11
+ if (pluginOptions.disabled) {
12
+ if (pluginOptions.debugging) {
13
+ console.log('[Auto-Translate Plugin] Plugin is disabled, skipping all modifications');
14
+ }
15
+ return config;
16
+ }
9
17
  // Validate configuration
10
18
  if (!config.collections) {
11
19
  config.collections = [];
@@ -75,21 +83,32 @@ export const autoTranslate = (pluginOptions)=>(config)=>{
75
83
  if (!collection.hooks) {
76
84
  collection.hooks = {};
77
85
  }
78
- if (!collection.hooks.afterChange) {
79
- collection.hooks.afterChange = [];
86
+ if (!collection.hooks.afterOperation) {
87
+ collection.hooks.afterOperation = [];
80
88
  }
81
89
  // Main translation hook
82
- collection.hooks.afterChange.push(async ({ doc, operation, previousDoc, req })=>{
90
+ collection.hooks.afterOperation.push(async ({ operation, req, result })=>{
83
91
  // Only process create and update operations
84
- if (operation !== 'create' && operation !== 'update') {
85
- return doc;
92
+ if (operation !== 'create' && operation !== 'updateByID') {
93
+ if (pluginOptions.debugging) {
94
+ req.payload.logger.error(`[Auto-Translate Plugin] Skipping translation - not create or update operation: ${operation}`);
95
+ }
96
+ return result;
86
97
  }
98
+ // For create/update operations, result should have a id property
99
+ if (!result || typeof result !== 'object' || !('id' in result)) {
100
+ if (pluginOptions.debugging) {
101
+ req.payload.logger.error(`[Auto-Translate Plugin] No document found in result: ${JSON.stringify(result)}`);
102
+ }
103
+ return result;
104
+ }
105
+ const doc = result;
87
106
  // Only translate if editing from default locale
88
107
  if (req.locale !== defaultLocale) {
89
108
  if (pluginOptions.debugging) {
90
109
  req.payload.logger.info(`[Auto-Translate Plugin] Skipping translation - not default locale (current: ${req.locale}, default: ${defaultLocale})`);
91
110
  }
92
- return doc;
111
+ return result;
93
112
  }
94
113
  // Skip translation for drafts when autosave is enabled
95
114
  // Only translate when document is published
@@ -97,14 +116,14 @@ export const autoTranslate = (pluginOptions)=>(config)=>{
97
116
  if (pluginOptions.debugging) {
98
117
  req.payload.logger.info(`[Auto-Translate Plugin] Skipping translation - document is a draft (status: ${doc._status})`);
99
118
  }
100
- return doc;
119
+ return result;
101
120
  }
102
121
  // Check if translation sync is enabled
103
122
  if (!doc.translationSync) {
104
123
  if (pluginOptions.debugging) {
105
124
  req.payload.logger.info(`[Auto-Translate Plugin] Skipping translation - translationSync disabled for ${collectionSlug}:${doc.id}`);
106
125
  }
107
- return doc;
126
+ return result;
108
127
  }
109
128
  if (pluginOptions.debugging) {
110
129
  req.payload.logger.info(`[Auto-Translate Plugin] Processing ${collectionSlug} document ${operation}: ${doc.id}`);
@@ -120,7 +139,7 @@ export const autoTranslate = (pluginOptions)=>(config)=>{
120
139
  // Get field-level exclusions for this locale (only if exclusions are enabled)
121
140
  let excludedPaths = [];
122
141
  if (enableExclusions) {
123
- excludedPaths = await translationService.getExclusions(req.payload, collectionSlug, doc.id, targetLocale);
142
+ excludedPaths = await translationService.getExclusions(req.payload, collectionSlug, doc.id.toString(), targetLocale);
124
143
  }
125
144
  // Get global/collection-level excluded fields
126
145
  const configExcludedFields = translationService.getConfigExcludedFields(collectionSlug);
@@ -179,7 +198,8 @@ export const autoTranslate = (pluginOptions)=>(config)=>{
179
198
  // Prevent infinite loop - don't trigger hooks
180
199
  context: {
181
200
  skipAutoTranslate: true
182
- }
201
+ },
202
+ req
183
203
  });
184
204
  if (pluginOptions.debugging) {
185
205
  req.payload.logger.info(`[Auto-Translate Plugin] Successfully translated ${collectionSlug}:${doc.id} to ${targetLocale}`);
@@ -204,31 +224,33 @@ export const autoTranslate = (pluginOptions)=>(config)=>{
204
224
  }
205
225
  // Log additional context if it's an OpenAI error
206
226
  if (error && typeof error === 'object' && 'error' in error) {
207
- req.payload.logger.error('OpenAI error details:', JSON.stringify(error, null, 2));
227
+ req.payload.logger.error('OpenAI error details:');
228
+ req.payload.logger.error(JSON.stringify(error, null, 2));
208
229
  }
209
230
  // Continue with other locales even if one fails
210
231
  }
211
232
  }
212
- return doc;
233
+ return result;
213
234
  });
214
235
  // Prevent infinite loops - skip translation if triggered by our own update
215
- const originalAfterChangeHooks = [
216
- ...collection.hooks.afterChange || []
236
+ const originalAfterOperationHooks = [
237
+ ...collection.hooks.afterOperation || []
217
238
  ];
218
- collection.hooks.afterChange = [
239
+ collection.hooks.afterOperation = [
219
240
  async (args)=>{
220
241
  // Skip if this update was triggered by auto-translate
221
- if (args.context?.skipAutoTranslate) {
222
- return args.doc;
242
+ // Context might not be available on all operations
243
+ if ('req' in args && args.req?.context?.skipAutoTranslate) {
244
+ return args.result;
223
245
  }
224
246
  // Run all hooks including translation
225
- for (const hook of originalAfterChangeHooks){
247
+ for (const hook of originalAfterOperationHooks){
226
248
  const result = await hook(args);
227
249
  if (result !== undefined) {
228
- args.doc = result;
250
+ args.result = result;
229
251
  }
230
252
  }
231
- return args.doc;
253
+ return args.result;
232
254
  }
233
255
  ];
234
256
  if (pluginOptions.debugging) {
@@ -236,12 +258,6 @@ export const autoTranslate = (pluginOptions)=>(config)=>{
236
258
  }
237
259
  }
238
260
  }
239
- /**
240
- * If the plugin is disabled, we still want to keep added collections/fields
241
- * so the database schema is consistent which is important for migrations.
242
- */ if (pluginOptions.disabled) {
243
- return config;
244
- }
245
261
  return config;
246
262
  };
247
263
  /**
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { Config } from 'payload'\n\nimport type { AutoTranslateConfig } from './types/index.js'\n\nimport { getTranslationExclusionsCollection } from './collections/translationExclusions.js'\nimport { getTranslationSettingsGlobal } from './globals/translationSettings.js'\nimport { TranslationService } from './services/translationService.js'\nimport { injectTranslationControls } from './utilities/injectTranslationControls.js'\n\nexport { getTranslationExclusionsCollection } from './collections/translationExclusions.js'\nexport { getTranslationSettingsGlobal } from './globals/translationSettings.js'\nexport * from './types/index.js'\n\nexport const autoTranslate =\n (pluginOptions: AutoTranslateConfig) =>\n (config: Config): Config => {\n // Validate configuration\n if (!config.collections) {\n config.collections = []\n }\n\n if (!config.localization) {\n console.warn(\n '[Auto-Translate Plugin] No localization config found. Plugin will not function properly.',\n )\n return config\n }\n\n const localizationConfig = config.localization\n const defaultLocale = localizationConfig.defaultLocale\n const allLocales = Array.isArray(localizationConfig.locales)\n ? localizationConfig.locales.map((l) => (typeof l === 'string' ? l : l.code))\n : []\n\n // Default enableExclusions to true for backward compatibility\n const enableExclusions = pluginOptions.enableExclusions !== false\n\n if (pluginOptions.debugging) {\n console.log('[Auto-Translate Plugin] Configuration:')\n console.log('- Default locale:', defaultLocale)\n console.log('- All locales:', allLocales)\n console.log('- Enabled collections:', Object.keys(pluginOptions.collections || {}))\n console.log('- Exclusions enabled:', enableExclusions)\n }\n\n // Add translation exclusions collection (only if exclusions are enabled)\n if (enableExclusions) {\n const exclusionsSlug = pluginOptions.translationExclusionsSlug || 'translation-exclusions'\n config.collections.push(getTranslationExclusionsCollection(exclusionsSlug))\n }\n\n // Add translation settings global\n if (!config.globals) {\n config.globals = []\n }\n const settingsSlug = pluginOptions.translationSettingsSlug || 'translation-settings'\n config.globals.push(getTranslationSettingsGlobal(settingsSlug))\n\n // Initialize translation service\n const translationService = new TranslationService(pluginOptions)\n\n // Configure collections with auto-translate\n if (pluginOptions.collections) {\n for (const collectionSlug in pluginOptions.collections) {\n const collectionConfig = pluginOptions.collections[collectionSlug]\n\n // Skip if disabled\n if (\n collectionConfig === false ||\n (typeof collectionConfig === 'object' && collectionConfig.enabled === false)\n ) {\n continue\n }\n\n const collection = config.collections.find((c) => c.slug === collectionSlug)\n\n if (!collection) {\n console.warn(`[Auto-Translate Plugin] Collection \"${collectionSlug}\" not found in config`)\n continue\n }\n\n // Add translationSync field to collection\n collection.fields.push({\n name: 'translationSync',\n type: 'checkbox',\n admin: {\n description:\n 'When enabled, changes in the default language will automatically translate to other languages',\n position: 'sidebar',\n },\n defaultValue: pluginOptions.enableTranslationSyncByDefault ?? true,\n label: 'Enable Auto-Translation',\n })\n\n // Auto-inject TranslationControl component into all localized fields\n // Only inject if exclusions are enabled (otherwise there's nothing to control)\n if (enableExclusions && pluginOptions.autoInjectUI !== false) {\n collection.fields = injectTranslationControls(collection.fields, defaultLocale)\n\n if (pluginOptions.debugging) {\n console.log(`[Auto-Translate Plugin] Auto-injected UI controls for: ${collectionSlug}`)\n }\n }\n\n // Add hooks for translation\n if (!collection.hooks) {\n collection.hooks = {}\n }\n\n if (!collection.hooks.afterChange) {\n collection.hooks.afterChange = []\n }\n\n // Main translation hook\n collection.hooks.afterChange.push(async ({ doc, operation, previousDoc, req }) => {\n // Only process create and update operations\n if (operation !== 'create' && operation !== 'update') {\n return doc\n }\n\n // Only translate if editing from default locale\n if (req.locale !== defaultLocale) {\n if (pluginOptions.debugging) {\n req.payload.logger.info(\n `[Auto-Translate Plugin] Skipping translation - not default locale (current: ${req.locale}, default: ${defaultLocale})`,\n )\n }\n return doc\n }\n\n // Skip translation for drafts when autosave is enabled\n // Only translate when document is published\n if (doc._status && doc._status !== 'published') {\n if (pluginOptions.debugging) {\n req.payload.logger.info(\n `[Auto-Translate Plugin] Skipping translation - document is a draft (status: ${doc._status})`,\n )\n }\n return doc\n }\n\n // Check if translation sync is enabled\n if (!doc.translationSync) {\n if (pluginOptions.debugging) {\n req.payload.logger.info(\n `[Auto-Translate Plugin] Skipping translation - translationSync disabled for ${collectionSlug}:${doc.id}`,\n )\n }\n return doc\n }\n\n if (pluginOptions.debugging) {\n req.payload.logger.info(\n `[Auto-Translate Plugin] Processing ${collectionSlug} document ${operation}: ${doc.id}`,\n )\n }\n\n // Get secondary locales (all locales except default)\n const secondaryLocales = allLocales.filter((locale) => locale !== defaultLocale)\n\n // Translate to each secondary locale\n for (const targetLocale of secondaryLocales) {\n try {\n if (pluginOptions.debugging) {\n req.payload.logger.info(\n `[Auto-Translate Plugin] Translating ${collectionSlug}:${doc.id} from ${defaultLocale} to ${targetLocale}`,\n )\n }\n\n // Get field-level exclusions for this locale (only if exclusions are enabled)\n let excludedPaths: string[] = []\n if (enableExclusions) {\n excludedPaths = await translationService.getExclusions(\n req.payload,\n collectionSlug,\n doc.id,\n targetLocale,\n )\n }\n\n // Get global/collection-level excluded fields\n const configExcludedFields =\n translationService.getConfigExcludedFields(collectionSlug)\n const allExcludedPaths = [...excludedPaths, ...configExcludedFields]\n\n if (pluginOptions.debugging && allExcludedPaths.length > 0) {\n req.payload.logger.info(\n `[Auto-Translate Plugin] Excluded paths for ${targetLocale}: ${allExcludedPaths.join(', ')}`,\n )\n }\n\n // Get existing document in target locale to preserve excluded fields\n // Only needed if exclusions are enabled\n let existingDoc: any = null\n if (enableExclusions && allExcludedPaths.length > 0) {\n try {\n const existingResult = await req.payload.findByID({\n id: doc.id,\n collection: collectionSlug,\n fallbackLocale: false,\n locale: targetLocale,\n })\n existingDoc = existingResult\n } catch (error) {\n // Document doesn't exist in this locale yet, that's okay\n if (pluginOptions.debugging) {\n req.payload.logger.info(\n `[Auto-Translate Plugin] No existing document for ${targetLocale}, will create new`,\n )\n }\n }\n }\n\n // Translate the document\n const translatedData = await translationService.translate({\n collection: collectionSlug,\n data: doc,\n excludedPaths: allExcludedPaths,\n fromLocale: defaultLocale,\n payload: req.payload,\n toLocale: targetLocale,\n })\n\n // Merge translated data with existing, preserving excluded fields\n const finalData = translatedData\n if (existingDoc && allExcludedPaths.length > 0) {\n // Preserve excluded fields from existing document\n for (const excludedPath of allExcludedPaths) {\n const existingValue = getNestedValue(existingDoc, excludedPath)\n if (existingValue !== undefined) {\n setNestedValue(finalData, excludedPath, existingValue)\n }\n }\n }\n\n // Update the document in the target locale\n await req.payload.update({\n id: doc.id,\n collection: collectionSlug,\n data: finalData,\n locale: targetLocale,\n // Prevent infinite loop - don't trigger hooks\n context: {\n skipAutoTranslate: true,\n },\n })\n\n if (pluginOptions.debugging) {\n req.payload.logger.info(\n `[Auto-Translate Plugin] Successfully translated ${collectionSlug}:${doc.id} to ${targetLocale}`,\n )\n }\n } catch (error) {\n // Log detailed error information\n const errorMessage = error instanceof Error ? error.message : String(error)\n const errorStack = error instanceof Error ? error.stack : undefined\n const errorDetails = {\n collection: collectionSlug,\n documentId: doc.id,\n fromLocale: defaultLocale,\n message: errorMessage,\n stack: errorStack,\n toLocale: targetLocale,\n }\n\n req.payload.logger.error(\n `[Auto-Translate Plugin] Error translating ${collectionSlug}:${doc.id} to ${targetLocale}:`,\n )\n req.payload.logger.error(errorMessage)\n\n if (pluginOptions.debugging && errorStack) {\n req.payload.logger.error('Stack trace:')\n req.payload.logger.error(errorStack)\n }\n\n // Log additional context if it's an OpenAI error\n if (error && typeof error === 'object' && 'error' in error) {\n req.payload.logger.error('OpenAI error details:', JSON.stringify(error, null, 2))\n }\n\n // Continue with other locales even if one fails\n }\n }\n\n return doc\n })\n\n // Prevent infinite loops - skip translation if triggered by our own update\n const originalAfterChangeHooks = [...(collection.hooks.afterChange || [])]\n collection.hooks.afterChange = [\n async (args) => {\n // Skip if this update was triggered by auto-translate\n if (args.context?.skipAutoTranslate) {\n return args.doc\n }\n\n // Run all hooks including translation\n for (const hook of originalAfterChangeHooks) {\n const result = await hook(args)\n if (result !== undefined) {\n args.doc = result\n }\n }\n\n return args.doc\n },\n ]\n\n if (pluginOptions.debugging) {\n console.log(`[Auto-Translate Plugin] Configured collection: ${collectionSlug}`)\n }\n }\n }\n\n /**\n * If the plugin is disabled, we still want to keep added collections/fields\n * so the database schema is consistent which is important for migrations.\n */\n if (pluginOptions.disabled) {\n return config\n }\n\n return config\n }\n\n/**\n * Helper function to get nested value from object using dot notation\n */\nfunction getNestedValue(obj: any, path: string): any {\n return path.split('.').reduce((current, part) => {\n if (current === null || current === undefined) {\n return undefined\n }\n return current[part]\n }, obj)\n}\n\n/**\n * Helper function to set nested value in object using dot notation\n */\nfunction setNestedValue(obj: any, path: string, value: any): void {\n const parts = path.split('.')\n let current = obj\n\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i]\n if (!(part in current) || current[part] === null || typeof current[part] !== 'object') {\n // Check if next part is a number (array index)\n const nextPart = parts[i + 1]\n current[part] = /^\\d+$/.test(nextPart) ? [] : {}\n }\n current = current[part]\n }\n\n current[parts[parts.length - 1]] = value\n}\n"],"names":["getTranslationExclusionsCollection","getTranslationSettingsGlobal","TranslationService","injectTranslationControls","autoTranslate","pluginOptions","config","collections","localization","console","warn","localizationConfig","defaultLocale","allLocales","Array","isArray","locales","map","l","code","enableExclusions","debugging","log","Object","keys","exclusionsSlug","translationExclusionsSlug","push","globals","settingsSlug","translationSettingsSlug","translationService","collectionSlug","collectionConfig","enabled","collection","find","c","slug","fields","name","type","admin","description","position","defaultValue","enableTranslationSyncByDefault","label","autoInjectUI","hooks","afterChange","doc","operation","previousDoc","req","locale","payload","logger","info","_status","translationSync","id","secondaryLocales","filter","targetLocale","excludedPaths","getExclusions","configExcludedFields","getConfigExcludedFields","allExcludedPaths","length","join","existingDoc","existingResult","findByID","fallbackLocale","error","translatedData","translate","data","fromLocale","toLocale","finalData","excludedPath","existingValue","getNestedValue","undefined","setNestedValue","update","context","skipAutoTranslate","errorMessage","Error","message","String","errorStack","stack","errorDetails","documentId","JSON","stringify","originalAfterChangeHooks","args","hook","result","disabled","obj","path","split","reduce","current","part","value","parts","i","nextPart","test"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { Config } from 'payload'\n\nimport type { AutoTranslateConfig } from './types/index.js'\n\nimport { getTranslationExclusionsCollection } from './collections/translationExclusions.js'\nimport { getTranslationSettingsGlobal } from './globals/translationSettings.js'\nimport { TranslationService } from './services/translationService.js'\nimport { injectTranslationControls } from './utilities/injectTranslationControls.js'\n\nexport { getTranslationExclusionsCollection } from './collections/translationExclusions.js'\nexport { getTranslationSettingsGlobal } from './globals/translationSettings.js'\nexport { TranslationService } from './services/translationService.js'\nexport * from './types/index.js'\n\nexport const autoTranslate =\n (pluginOptions: AutoTranslateConfig) =>\n (config: Config): Config => {\n // If the plugin is disabled, return config immediately without any modifications\n if (pluginOptions.disabled) {\n if (pluginOptions.debugging) {\n console.log('[Auto-Translate Plugin] Plugin is disabled, skipping all modifications')\n }\n return config\n }\n\n // Validate configuration\n if (!config.collections) {\n config.collections = []\n }\n\n if (!config.localization) {\n console.warn(\n '[Auto-Translate Plugin] No localization config found. Plugin will not function properly.',\n )\n return config\n }\n\n const localizationConfig = config.localization\n const defaultLocale = localizationConfig.defaultLocale\n const allLocales = Array.isArray(localizationConfig.locales)\n ? localizationConfig.locales.map((l) => (typeof l === 'string' ? l : l.code))\n : []\n\n // Default enableExclusions to true for backward compatibility\n const enableExclusions = pluginOptions.enableExclusions !== false\n\n if (pluginOptions.debugging) {\n console.log('[Auto-Translate Plugin] Configuration:')\n console.log('- Default locale:', defaultLocale)\n console.log('- All locales:', allLocales)\n console.log('- Enabled collections:', Object.keys(pluginOptions.collections || {}))\n console.log('- Exclusions enabled:', enableExclusions)\n }\n\n // Add translation exclusions collection (only if exclusions are enabled)\n if (enableExclusions) {\n const exclusionsSlug = pluginOptions.translationExclusionsSlug || 'translation-exclusions'\n config.collections.push(getTranslationExclusionsCollection(exclusionsSlug))\n }\n\n // Add translation settings global\n if (!config.globals) {\n config.globals = []\n }\n const settingsSlug = pluginOptions.translationSettingsSlug || 'translation-settings'\n config.globals.push(getTranslationSettingsGlobal(settingsSlug))\n\n // Initialize translation service\n const translationService = new TranslationService(pluginOptions)\n\n // Configure collections with auto-translate\n if (pluginOptions.collections) {\n for (const collectionSlug in pluginOptions.collections) {\n const collectionConfig = pluginOptions.collections[collectionSlug]\n\n // Skip if disabled\n if (\n collectionConfig === false ||\n (typeof collectionConfig === 'object' && collectionConfig.enabled === false)\n ) {\n continue\n }\n\n const collection = config.collections.find((c) => c.slug === collectionSlug)\n\n if (!collection) {\n console.warn(`[Auto-Translate Plugin] Collection \"${collectionSlug}\" not found in config`)\n continue\n }\n\n // Add translationSync field to collection\n collection.fields.push({\n name: 'translationSync',\n type: 'checkbox',\n admin: {\n description:\n 'When enabled, changes in the default language will automatically translate to other languages',\n position: 'sidebar',\n },\n defaultValue: pluginOptions.enableTranslationSyncByDefault ?? true,\n label: 'Enable Auto-Translation',\n })\n\n // Auto-inject TranslationControl component into all localized fields\n // Only inject if exclusions are enabled (otherwise there's nothing to control)\n if (enableExclusions && pluginOptions.autoInjectUI !== false) {\n collection.fields = injectTranslationControls(collection.fields, defaultLocale)\n\n if (pluginOptions.debugging) {\n console.log(`[Auto-Translate Plugin] Auto-injected UI controls for: ${collectionSlug}`)\n }\n }\n\n // Add hooks for translation\n if (!collection.hooks) {\n collection.hooks = {}\n }\n\n if (!collection.hooks.afterOperation) {\n collection.hooks.afterOperation = []\n }\n\n // Main translation hook\n collection.hooks.afterOperation.push(async ({ operation, req, result }) => {\n // Only process create and update operations\n if (operation !== 'create' && operation !== 'updateByID') {\n if (pluginOptions.debugging) {\n req.payload.logger.error(\n `[Auto-Translate Plugin] Skipping translation - not create or update operation: ${operation}`,\n )\n }\n return result\n }\n\n // For create/update operations, result should have a id property\n if (!result || typeof result !== 'object' || !('id' in result)) {\n if (pluginOptions.debugging) {\n req.payload.logger.error(\n `[Auto-Translate Plugin] No document found in result: ${JSON.stringify(result)}`,\n )\n }\n return result\n }\n\n const doc = result\n\n // Only translate if editing from default locale\n if (req.locale !== defaultLocale) {\n if (pluginOptions.debugging) {\n req.payload.logger.info(\n `[Auto-Translate Plugin] Skipping translation - not default locale (current: ${req.locale}, default: ${defaultLocale})`,\n )\n }\n return result\n }\n\n // Skip translation for drafts when autosave is enabled\n // Only translate when document is published\n if (doc._status && doc._status !== 'published') {\n if (pluginOptions.debugging) {\n req.payload.logger.info(\n `[Auto-Translate Plugin] Skipping translation - document is a draft (status: ${doc._status})`,\n )\n }\n return result\n }\n\n // Check if translation sync is enabled\n if (!doc.translationSync) {\n if (pluginOptions.debugging) {\n req.payload.logger.info(\n `[Auto-Translate Plugin] Skipping translation - translationSync disabled for ${collectionSlug}:${doc.id}`,\n )\n }\n return result\n }\n\n if (pluginOptions.debugging) {\n req.payload.logger.info(\n `[Auto-Translate Plugin] Processing ${collectionSlug} document ${operation}: ${doc.id}`,\n )\n }\n\n // Get secondary locales (all locales except default)\n const secondaryLocales = allLocales.filter((locale) => locale !== defaultLocale)\n\n // Translate to each secondary locale\n for (const targetLocale of secondaryLocales) {\n try {\n if (pluginOptions.debugging) {\n req.payload.logger.info(\n `[Auto-Translate Plugin] Translating ${collectionSlug}:${doc.id} from ${defaultLocale} to ${targetLocale}`,\n )\n }\n\n // Get field-level exclusions for this locale (only if exclusions are enabled)\n let excludedPaths: string[] = []\n if (enableExclusions) {\n excludedPaths = await translationService.getExclusions(\n req.payload,\n collectionSlug,\n doc.id.toString(),\n targetLocale,\n )\n }\n\n // Get global/collection-level excluded fields\n const configExcludedFields =\n translationService.getConfigExcludedFields(collectionSlug)\n const allExcludedPaths = [...excludedPaths, ...configExcludedFields]\n\n if (pluginOptions.debugging && allExcludedPaths.length > 0) {\n req.payload.logger.info(\n `[Auto-Translate Plugin] Excluded paths for ${targetLocale}: ${allExcludedPaths.join(', ')}`,\n )\n }\n\n // Get existing document in target locale to preserve excluded fields\n // Only needed if exclusions are enabled\n let existingDoc: any = null\n if (enableExclusions && allExcludedPaths.length > 0) {\n try {\n const existingResult = await req.payload.findByID({\n id: doc.id,\n collection: collectionSlug,\n fallbackLocale: false,\n locale: targetLocale,\n })\n existingDoc = existingResult\n } catch (error) {\n // Document doesn't exist in this locale yet, that's okay\n if (pluginOptions.debugging) {\n req.payload.logger.info(\n `[Auto-Translate Plugin] No existing document for ${targetLocale}, will create new`,\n )\n }\n }\n }\n\n // Translate the document\n const translatedData = await translationService.translate({\n collection: collectionSlug,\n data: doc,\n excludedPaths: allExcludedPaths,\n fromLocale: defaultLocale,\n payload: req.payload,\n toLocale: targetLocale,\n })\n\n // Merge translated data with existing, preserving excluded fields\n const finalData = translatedData\n if (existingDoc && allExcludedPaths.length > 0) {\n // Preserve excluded fields from existing document\n for (const excludedPath of allExcludedPaths) {\n const existingValue = getNestedValue(existingDoc, excludedPath)\n if (existingValue !== undefined) {\n setNestedValue(finalData, excludedPath, existingValue)\n }\n }\n }\n\n // Update the document in the target locale\n await req.payload.update({\n id: doc.id,\n collection: collectionSlug,\n data: finalData,\n locale: targetLocale,\n // Prevent infinite loop - don't trigger hooks\n context: {\n skipAutoTranslate: true,\n },\n req,\n })\n\n if (pluginOptions.debugging) {\n req.payload.logger.info(\n `[Auto-Translate Plugin] Successfully translated ${collectionSlug}:${doc.id} to ${targetLocale}`,\n )\n }\n } catch (error) {\n // Log detailed error information\n const errorMessage = error instanceof Error ? error.message : String(error)\n const errorStack = error instanceof Error ? error.stack : undefined\n const errorDetails = {\n collection: collectionSlug,\n documentId: doc.id,\n fromLocale: defaultLocale,\n message: errorMessage,\n stack: errorStack,\n toLocale: targetLocale,\n }\n\n req.payload.logger.error(\n `[Auto-Translate Plugin] Error translating ${collectionSlug}:${doc.id} to ${targetLocale}:`,\n )\n req.payload.logger.error(errorMessage)\n\n if (pluginOptions.debugging && errorStack) {\n req.payload.logger.error('Stack trace:')\n req.payload.logger.error(errorStack)\n }\n\n // Log additional context if it's an OpenAI error\n if (error && typeof error === 'object' && 'error' in error) {\n req.payload.logger.error('OpenAI error details:')\n req.payload.logger.error(JSON.stringify(error, null, 2))\n }\n\n // Continue with other locales even if one fails\n }\n }\n\n return result\n })\n\n // Prevent infinite loops - skip translation if triggered by our own update\n const originalAfterOperationHooks = [...(collection.hooks.afterOperation || [])]\n collection.hooks.afterOperation = [\n async (args) => {\n // Skip if this update was triggered by auto-translate\n // Context might not be available on all operations\n if ('req' in args && args.req?.context?.skipAutoTranslate) {\n return args.result\n }\n\n // Run all hooks including translation\n for (const hook of originalAfterOperationHooks) {\n const result = await hook(args)\n if (result !== undefined) {\n args.result = result\n }\n }\n\n return args.result\n },\n ]\n\n if (pluginOptions.debugging) {\n console.log(`[Auto-Translate Plugin] Configured collection: ${collectionSlug}`)\n }\n }\n }\n\n return config\n }\n\n/**\n * Helper function to get nested value from object using dot notation\n */\nfunction getNestedValue(obj: any, path: string): any {\n return path.split('.').reduce((current, part) => {\n if (current === null || current === undefined) {\n return undefined\n }\n return current[part]\n }, obj)\n}\n\n/**\n * Helper function to set nested value in object using dot notation\n */\nfunction setNestedValue(obj: any, path: string, value: any): void {\n const parts = path.split('.')\n let current = obj\n\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i]\n if (!(part in current) || current[part] === null || typeof current[part] !== 'object') {\n // Check if next part is a number (array index)\n const nextPart = parts[i + 1]\n current[part] = /^\\d+$/.test(nextPart) ? [] : {}\n }\n current = current[part]\n }\n\n current[parts[parts.length - 1]] = value\n}\n"],"names":["getTranslationExclusionsCollection","getTranslationSettingsGlobal","TranslationService","injectTranslationControls","autoTranslate","pluginOptions","config","disabled","debugging","console","log","collections","localization","warn","localizationConfig","defaultLocale","allLocales","Array","isArray","locales","map","l","code","enableExclusions","Object","keys","exclusionsSlug","translationExclusionsSlug","push","globals","settingsSlug","translationSettingsSlug","translationService","collectionSlug","collectionConfig","enabled","collection","find","c","slug","fields","name","type","admin","description","position","defaultValue","enableTranslationSyncByDefault","label","autoInjectUI","hooks","afterOperation","operation","req","result","payload","logger","error","JSON","stringify","doc","locale","info","_status","translationSync","id","secondaryLocales","filter","targetLocale","excludedPaths","getExclusions","toString","configExcludedFields","getConfigExcludedFields","allExcludedPaths","length","join","existingDoc","existingResult","findByID","fallbackLocale","translatedData","translate","data","fromLocale","toLocale","finalData","excludedPath","existingValue","getNestedValue","undefined","setNestedValue","update","context","skipAutoTranslate","errorMessage","Error","message","String","errorStack","stack","errorDetails","documentId","originalAfterOperationHooks","args","hook","obj","path","split","reduce","current","part","value","parts","i","nextPart","test"],"mappings":"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"}
@@ -37,10 +37,6 @@ export declare class TranslationService {
37
37
  * Determines if a string should be skipped from translation
38
38
  */
39
39
  private shouldSkipString;
40
- /**
41
- * Translates using OpenAI API (optimized version)
42
- */
43
- private translateWithOpenAI;
44
40
  /**
45
41
  * Legacy translation method (sends entire structure)
46
42
  */
@@ -57,6 +53,11 @@ export declare class TranslationService {
57
53
  * Main translation method
58
54
  */
59
55
  translate(options: TranslateOptions): Promise<any>;
56
+ /**
57
+ * Translates using OpenAI API (optimized version)
58
+ * This method is now public and can be used directly in your application
59
+ */
60
+ translateWithOpenAI(data: any, fromLocale: string, toLocale: string, payload: Payload): Promise<any>;
60
61
  /**
61
62
  * Updates translation exclusions for a document
62
63
  */