feat(cms): implement multi-language support across frontend and admin UI

This commit is contained in:
Your Name committed 2026-06-14 09:00:57 -04:00
1 parent 730e2a7b48
commit eac45dd4a7
62 files changed
+1377 -5116

No files matched your search

+137 -2
View File
@@ -7,9 +7,9 @@ import {
import axios from "axios";
import * as FormData from "form-data";
const BACKEND_URL = process.env.BACKEND_URL || "http://localhost:3000/api";
const BACKEND_URL = "http://localhost:3051/api";
const ADMIN_USERNAME = process.env.ADMIN_USERNAME || "admin";
const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD || "homaroma123";
const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD || "homaroma123"; // เปลี่ยนรหัสผ่านตรงนี้ให้ตรงกับ Production ด้วยนะครับ
let authToken = "";
@@ -100,6 +100,91 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
required: ["id", "lang", "name"]
}
},
{
name: "update_scent_translation",
description: "Add or update translations for a specific scent.",
inputSchema: {
type: "object",
properties: {
id: { type: "number", description: "Scent ID" },
lang: { type: "string", description: "Language code (th, en, ja, zh, vi, ko)" },
name: { type: "string", description: "Translated scent name" }
},
required: ["id", "lang", "name"]
}
},
{
name: "update_page_translation",
description: "Add or update translations for a specific page.",
inputSchema: {
type: "object",
properties: {
id: { type: "number", description: "Page ID" },
lang: { type: "string", description: "Language code (th, en, ja, zh, vi, ko)" },
title: { type: "string", description: "Translated page title" }
},
required: ["id", "lang", "title"]
}
},
{
name: "update_hero_translation",
description: "Add or update translations for a specific hero.",
inputSchema: {
type: "object",
properties: {
id: { type: "number", description: "Hero ID" },
lang: { type: "string", description: "Language code" },
tagline: { type: "string" },
title: { type: "string" },
description: { type: "string" },
buttonText: { type: "string" }
},
required: ["id", "lang"]
}
},
{
name: "update_menu_item_translation",
description: "Add or update translations for a specific menu item.",
inputSchema: {
type: "object",
properties: {
id: { type: "number", description: "Menu Item ID" },
lang: { type: "string", description: "Language code" },
label: { type: "string", description: "Translated menu item label" }
},
required: ["id", "lang", "label"]
}
},
{
name: "update_store_settings_translation",
description: "Add or update translations for store settings.",
inputSchema: {
type: "object",
properties: {
lang: { type: "string", description: "Language code" },
footerDescription: { type: "string" },
newsletterTitle: { type: "string" },
newsletterDescription: { type: "string" },
newsletterPlaceholder: { type: "string" },
newsletterButtonText: { type: "string" }
},
required: ["lang"]
}
},
{
name: "update_article_translation",
description: "Add or update translations for a specific article.",
inputSchema: {
type: "object",
properties: {
id: { type: "number", description: "Article ID" },
lang: { type: "string", description: "Language code" },
title: { type: "string" },
content: { type: "string" }
},
required: ["id", "lang"]
}
},
{
name: "update_product_content",
description: "Update product basic content (name, description, details)",
@@ -373,6 +458,56 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }]
};
}
case "update_scent_translation": {
const { id, lang, name } = params as any;
const res = await api.patch(`/products/scents/${id}/translations`, {
name: { [lang]: name }
});
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
}
case "update_page_translation": {
const { id, lang, title } = params as any;
const res = await api.patch(`/pages/${id}/translations`, {
title: { [lang]: title }
});
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
}
case "update_hero_translation": {
const { id, lang, tagline, title, description, buttonText } = params as any;
const payload: any = {};
if (tagline) payload.tagline = { [lang]: tagline };
if (title) payload.title = { [lang]: title };
if (description) payload.description = { [lang]: description };
if (buttonText) payload.buttonText = { [lang]: buttonText };
const res = await api.patch(`/hero/${id}/translations`, payload);
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
}
case "update_menu_item_translation": {
const { id, lang, label } = params as any;
const res = await api.patch(`/menus/items/${id}/translations`, {
label: { [lang]: label }
});
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
}
case "update_store_settings_translation": {
const { lang, footerDescription, newsletterTitle, newsletterDescription, newsletterPlaceholder, newsletterButtonText } = params as any;
const payload: any = {};
if (footerDescription) payload.footerDescription = { [lang]: footerDescription };
if (newsletterTitle) payload.newsletterTitle = { [lang]: newsletterTitle };
if (newsletterDescription) payload.newsletterDescription = { [lang]: newsletterDescription };
if (newsletterPlaceholder) payload.newsletterPlaceholder = { [lang]: newsletterPlaceholder };
if (newsletterButtonText) payload.newsletterButtonText = { [lang]: newsletterButtonText };
const res = await api.patch(`/settings/translations`, payload);
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
}
case "update_article_translation": {
const { id, lang, title, content } = params as any;
const payload: any = {};
if (title) payload.title = { [lang]: title };
if (content) payload.content = { [lang]: content };
const res = await api.patch(`/articles/${id}/translations`, payload);
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
}
case "update_product_content": {
const payload: any = {};