payload-translate 1.0.1 → 1.0.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.
@@ -88,11 +88,13 @@ export const translateHandler = async (req)=>{
88
88
  });
89
89
  // Apply translations to document
90
90
  const updatedData = applyTranslations(document, translatableFields, translations);
91
+ // Remove immutable system fields before update
92
+ const { id, createdAt, updatedAt, ...dataToUpdate } = updatedData;
91
93
  // Update document in target locale
92
94
  await payload.update({
93
95
  id: documentId,
94
96
  collection,
95
- data: updatedData,
97
+ data: dataToUpdate,
96
98
  locale: targetLocale
97
99
  });
98
100
  return Response.json({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/endpoints/translateHandler.ts"],"sourcesContent":["import type { PayloadHandler } from 'payload'\n\nimport type { TranslateRequestBody, TranslateResponse } from '../types.js'\n\nimport { translateWithGemini } from '../services/gemini.js'\nimport { applyTranslations } from '../utils/applyTranslations.js'\nimport { extractTranslatableFields } from '../utils/extractTranslatableFields.js'\n\nexport const translateHandler: PayloadHandler = async (req) => {\n try {\n const { payload, user } = req\n\n // Check authentication\n if (!user) {\n return Response.json({ error: 'Unauthorized', success: false } as TranslateResponse, {\n status: 401,\n })\n }\n\n // Parse request body\n const body = (await req.json?.()) as TranslateRequestBody | undefined\n if (!body) {\n return Response.json(\n { error: 'Invalid request body', success: false } as TranslateResponse,\n { status: 400 },\n )\n }\n const { collection, documentId, sourceLocale, targetLocale } = body\n\n // Validate request\n if (!collection || !documentId || !sourceLocale || !targetLocale) {\n return Response.json(\n { error: 'Missing required fields', success: false } as TranslateResponse,\n { status: 400 },\n )\n }\n\n // Get API key from config\n const apiKey = (payload.config.custom as Record<string, unknown>)?.translateApiKey as\n | string\n | undefined\n if (!apiKey) {\n return Response.json(\n { error: 'Translation API key not configured', success: false } as TranslateResponse,\n { status: 500 },\n )\n }\n\n // Fetch document in source locale\n const document = await payload.findByID({\n id: documentId,\n collection,\n depth: 0,\n locale: sourceLocale,\n })\n\n if (!document) {\n return Response.json({ error: 'Document not found', success: false } as TranslateResponse, {\n status: 404,\n })\n }\n\n // Get collection config to find localized fields\n const collectionConfig = payload.collections[collection]?.config\n if (!collectionConfig) {\n return Response.json({ error: 'Collection not found', success: false } as TranslateResponse, {\n status: 404,\n })\n }\n\n // Extract translatable fields\n const translatableFields = extractTranslatableFields(\n document as Record<string, unknown>,\n collectionConfig.fields,\n )\n\n if (translatableFields.length === 0) {\n return Response.json({\n message: 'No translatable fields found',\n success: true,\n translatedFields: 0,\n } as TranslateResponse)\n }\n\n // Prepare texts for translation\n const texts = translatableFields.map((f) => f.value)\n\n // Translate with Gemini\n const translations = await translateWithGemini({\n apiKey,\n sourceLocale,\n targetLocale,\n texts,\n })\n\n // Apply translations to document\n const updatedData = applyTranslations(\n document as Record<string, unknown>,\n translatableFields,\n translations,\n )\n\n // Update document in target locale\n await payload.update({\n id: documentId,\n collection,\n data: updatedData,\n locale: targetLocale,\n })\n\n return Response.json({\n message: `Successfully translated ${translatableFields.length} field(s)`,\n success: true,\n translatedFields: translatableFields.length,\n } as TranslateResponse)\n } catch (error) {\n console.error('Translation error:', error)\n return Response.json(\n {\n error: error instanceof Error ? error.message : 'Translation failed',\n success: false,\n } as TranslateResponse,\n { status: 500 },\n )\n }\n}\n"],"names":["translateWithGemini","applyTranslations","extractTranslatableFields","translateHandler","req","payload","user","Response","json","error","success","status","body","collection","documentId","sourceLocale","targetLocale","apiKey","config","custom","translateApiKey","document","findByID","id","depth","locale","collectionConfig","collections","translatableFields","fields","length","message","translatedFields","texts","map","f","value","translations","updatedData","update","data","console","Error"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/endpoints/translateHandler.ts"],"sourcesContent":["import type { PayloadHandler } from 'payload'\n\nimport type { TranslateRequestBody, TranslateResponse } from '../types.js'\n\nimport { translateWithGemini } from '../services/gemini.js'\nimport { applyTranslations } from '../utils/applyTranslations.js'\nimport { extractTranslatableFields } from '../utils/extractTranslatableFields.js'\n\nexport const translateHandler: PayloadHandler = async (req) => {\n try {\n const { payload, user } = req\n\n // Check authentication\n if (!user) {\n return Response.json({ error: 'Unauthorized', success: false } as TranslateResponse, {\n status: 401,\n })\n }\n\n // Parse request body\n const body = (await req.json?.()) as TranslateRequestBody | undefined\n if (!body) {\n return Response.json(\n { error: 'Invalid request body', success: false } as TranslateResponse,\n { status: 400 },\n )\n }\n const { collection, documentId, sourceLocale, targetLocale } = body\n\n // Validate request\n if (!collection || !documentId || !sourceLocale || !targetLocale) {\n return Response.json(\n { error: 'Missing required fields', success: false } as TranslateResponse,\n { status: 400 },\n )\n }\n\n // Get API key from config\n const apiKey = (payload.config.custom as Record<string, unknown>)?.translateApiKey as\n | string\n | undefined\n if (!apiKey) {\n return Response.json(\n { error: 'Translation API key not configured', success: false } as TranslateResponse,\n { status: 500 },\n )\n }\n\n // Fetch document in source locale\n const document = await payload.findByID({\n id: documentId,\n collection,\n depth: 0,\n locale: sourceLocale,\n })\n\n if (!document) {\n return Response.json({ error: 'Document not found', success: false } as TranslateResponse, {\n status: 404,\n })\n }\n\n // Get collection config to find localized fields\n const collectionConfig = payload.collections[collection]?.config\n if (!collectionConfig) {\n return Response.json({ error: 'Collection not found', success: false } as TranslateResponse, {\n status: 404,\n })\n }\n\n // Extract translatable fields\n const translatableFields = extractTranslatableFields(\n document as Record<string, unknown>,\n collectionConfig.fields,\n )\n\n if (translatableFields.length === 0) {\n return Response.json({\n message: 'No translatable fields found',\n success: true,\n translatedFields: 0,\n } as TranslateResponse)\n }\n\n // Prepare texts for translation\n const texts = translatableFields.map((f) => f.value)\n\n // Translate with Gemini\n const translations = await translateWithGemini({\n apiKey,\n sourceLocale,\n targetLocale,\n texts,\n })\n\n // Apply translations to document\n const updatedData = applyTranslations(\n document as Record<string, unknown>,\n translatableFields,\n translations,\n )\n\n // Remove immutable system fields before update\n const { id, createdAt, updatedAt, ...dataToUpdate } = updatedData\n\n // Update document in target locale\n await payload.update({\n id: documentId,\n collection,\n data: dataToUpdate,\n locale: targetLocale,\n })\n\n return Response.json({\n message: `Successfully translated ${translatableFields.length} field(s)`,\n success: true,\n translatedFields: translatableFields.length,\n } as TranslateResponse)\n } catch (error) {\n console.error('Translation error:', error)\n return Response.json(\n {\n error: error instanceof Error ? error.message : 'Translation failed',\n success: false,\n } as TranslateResponse,\n { status: 500 },\n )\n }\n}\n"],"names":["translateWithGemini","applyTranslations","extractTranslatableFields","translateHandler","req","payload","user","Response","json","error","success","status","body","collection","documentId","sourceLocale","targetLocale","apiKey","config","custom","translateApiKey","document","findByID","id","depth","locale","collectionConfig","collections","translatableFields","fields","length","message","translatedFields","texts","map","f","value","translations","updatedData","createdAt","updatedAt","dataToUpdate","update","data","console","Error"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payload-translate",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "AI-powered translation plugin for Payload",
5
5
  "license": "MIT",
6
6
  "author": "Bridger Tower",