CodeGym /Các khóa học /ChatGPT Apps /Chiến lược nội địa hóa cho App

Chiến lược nội địa hóa cho App

ChatGPT Apps
Mức độ , Bài học
Có sẵn

1. Tại sao phải nghĩ về nội địa hóa ngay trong ChatGPT App

Nếu bạn từng làm các ứng dụng web thông thường, nội địa hóa có lẽ gắn với i18n “cổ điển”: chuỗi giao diện, vài định dạng ngày và số, từ điển — và bạn cẩn thận dịch mọi thứ. Trong ChatGPT App thì thú vị hơn: có một nhân vật thứ ba — chính là mô hình LLM. Nó đọc mô tả công cụ của bạn, các prompt, kết quả, rồi suy luận và đưa ra quyết định.

Tức là ngôn ngữ không chỉ là “làm sao hiển thị văn bản đẹp cho người dùng”, mà còn là “làm sao để mô hình hiểu công cụ của bạn làm gì, khi nào cần gọi và truyền những tham số nào”. Nút “Mua” có dịch hơi vụng cũng được, người dùng vẫn hiểu. Nhưng nếu bạn mô tả một tool thanh toán mơ hồ, pha trộn giữa tiếng Nga và tiếng Anh, mô hình có thể không bao giờ gọi tool đó, hoặc gọi theo cách hoàn toàn khác với kỳ vọng của bạn.

Một điểm nữa: ChatGPT đã truyền cho máy chủ MCP của bạn các gợi ý về locale và vị trí người dùng — _meta["openai/locale"]_meta["openai/userLocation"]. Việc này diễn ra ở cấp độ các yêu cầu MCP tới công cụ, để bạn có thể thích ứng văn bản và dữ liệu theo ngôn ngữ và khu vực của người dùng. Nói cách khác, nền tảng đã “đưa sẵn” cho bạn ngữ cảnh, và nhiệm vụ của nhà phát triển là khai thác nó một cách có cân nhắc.

Vì vậy trong mô-đun này, chúng ta nhìn nội địa hóa như một khía cạnh kiến trúc của ChatGPT App, chứ không phải kiểu “dịch UI xong là xong”.

2. Những lớp cần nội địa hóa

Hãy nhìn App như một chiếc bánh nhiều lớp. Mỗi lớp đều có thể (và thường là nên) được nội địa hóa. Để không bị ngợp, ta bắt đầu với bản đồ tổng quan.

Tổng quan các lớp

Trước hết — bảng tổng quan, rồi ta phân tích từng phần.

Lớp Là gì Ví dụ Ảnh hưởng
Widget UI Toàn bộ frontend hiển thị trong widget Tiêu đề, nút, lỗi, gợi ý UX của người dùng
Văn bản mô hình và prompts System‑prompt và câu mẫu Hướng dẫn, mẫu trả lời Hành vi của ChatGPT
Dữ liệu và nội dung Văn bản mà App hiển thị và xử lý Danh mục sản phẩm, mô tả, ngày tháng, giá Cả UX lẫn độ chính xác trả lời
Mô tả tools/lược đồ Metadata của công cụ và các trường JSON Schema description, gợi ý kiểu dữ liệu Cách mô hình gọi tools của bạn
Commerce và pháp lý Mọi thứ liên quan tới mua bán và chính sách Tên SKU, Terms, Privacy, email Tính chính xác pháp lý, độ tin cậy

Thực chất đây là lớp đầu tiên của bản đồ nội địa hóa: sau đó ta sẽ thêm chiều sâu (cosmetic/ngữ nghĩa), ngôn ngữ và các phần tử cụ thể.

Bây giờ đi theo từng lớp lần lượt.

Widget UI

Lớp hiển nhiên nhất — giao diện widget. Với GiftGenius gồm:

  • tiêu đề các khối;
  • nhãn của các trường (“Người nhận”, “Ngân sách”, “Sở thích”);
  • các nút (“Chọn quà tặng”, “Xóa bộ lọc”);
  • gợi ý trong ô nhập (“ví dụ: đồng nghiệp, mẹ…”);
  • thông báo lỗi và trạng thái trống (“Không tìm thấy quà tặng”).

Trong một ứng dụng React thông thường, đây là những ứng viên đầu tiên được đưa vào từ điển. Ở đây cũng vậy, chỉ khác ở chỗ UI không phải toàn bộ App, mà chỉ là một “bộ mặt” của nó.

Chút nữa trong mô-đun, chúng ta sẽ xây kiến trúc i18n đúng chuẩn cho widget, nhưng ngay bây giờ điều quan trọng là: không nên có chuỗi trực tiếp trong JSX. Cho dù bạn mới hỗ trợ một ngôn ngữ, việc cấu trúc hóa văn bản UI ngay từ đầu vẫn rất tiện.

Ví dụ nhỏ với GiftGenius (chưa dùng thư viện i18n thực sự):


type Locale = "en" | "ru";

const uiText = {
  en: {
    title: "GiftGenius: find a perfect present",
    recipientLabel: "Recipient",
  },
  ru: {
    title: "GiftGenius: chọn món quà hoàn hảo",
    recipientLabel: "Người nhận",
  },
};

function GiftForm({ locale }: { locale: Locale }) {
  const t = uiText[locale];

  return (
    <div>
      <h2>{t.title}</h2>
      <label>{t.recipientLabel}</label>
      {/* các trường còn lại */}
    </div>
  );
}

Ở đây chúng ta chưa làm “nội địa hóa thật sự”, nhưng đã tách riêng rõ ràng lớp văn bản UI.

Văn bản GPT và prompts

Lớp tiếp theo — các văn bản hệ thống và trợ giúp, không hiển thị trực tiếp cho người dùng nhưng ảnh hưởng mạnh tới hành vi của mô hình:

  • system‑prompt của App (“Bạn là trợ lý chọn quà…”);
  • các mẫu giải thích bạn đưa cho mô hình (“Hãy tạo phần tóm tắt ngắn gọn về lựa chọn”);
  • các follow‑ups và gợi ý chuẩn bị sẵn cho mô hình (“gợi ý người dùng làm rõ ngân sách nếu…”).

Những văn bản này cũng có thể (và thường nên) được nội địa hóa. Ví dụ đơn giản: nếu người dùng viết bằng tiếng Việt, còn system‑prompt của bạn hoàn toàn bằng tiếng Anh, mô hình dĩ nhiên vẫn xử lý được, nhưng bạn đã tự đánh mất quyền kiểm soát chính xác về phong cách và cách diễn đạt cho ngôn ngữ đó.

Chút nữa, trong các bài về nội địa hóa prompts và mô tả (prompts/descriptions), chúng ta sẽ xem cách triển khai system‑prompts đa ngôn ngữ một cách cẩn thận. Ở đây cần nhấn mạnh: prompts cũng là một lớp có thể nội địa hóa, giống như UI.

Dữ liệu và nội dung

Tiếp theo là dữ liệu của bạn. Với GiftGenius, đó là danh mục quà tặng: tên, mô tả, danh mục, đôi khi là gợi ý cách sử dụng quà. Với App thương mại, đó còn là giá, đơn vị tiền tệ, đơn vị đo lường, định dạng ngày, v.v. Trong các đặc tả product feed cho ChatGPT (định dạng bạn mô tả sản phẩm/dịch vụ cho nền tảng), các trường văn bản (title, description) và giá được làm rõ để có thể hiển thị chính xác cho người dùng ngay trong ChatGPT.

Nếu bạn muốn App toàn cầu, với danh mục quà tặng sẽ có tối thiểu những câu hỏi sau:

  • chúng ta có lưu tên/mô tả theo nhiều ngôn ngữ không;
  • chọn ngôn ngữ nào để trả về cho người dùng như thế nào;
  • làm gì nếu chưa có bản dịch (fallback);
  • hiển thị tiền tệ và định dạng ngày/giá cho các khu vực khác nhau ra sao.

Ví dụ có kiểu cho danh mục:

type Locale = "en" | "ru";

interface LocalizedString {
  en: string;
  ru: string;
}

interface Gift {
  id: string;
  title: LocalizedString;
  description: LocalizedString;
  priceCents: number;
  currency: "USD" | "EUR" | "RUB";
}
function getLocalizedTitle(gift: Gift, locale: Locale) {
  return gift.title[locale] ?? gift.title.en;
}

Tức là nội địa hóa không chỉ ở frontend, mà còn ở cấu trúc dữ liệu trong cơ sở dữ liệu và tài nguyên MCP. Chúng ta sẽ quay lại điều này khi bàn về Gateway (cổng giữa ChatGPT và dịch vụ của bạn) và máy chủ MCP.

Mô tả tools và JSON Schema

Lớp thứ tư — mô tả công cụ và các tham số của nó. Chính qua đó mô hình hiểu khi nào cần gọi tool và truyền các tham số gì. Trong MCP, đó là title, description của công cụ và description ở các trường của JSON Schema.

Tài liệu Apps SDK nhấn mạnh rằng mô hình sử dụng tên, mô tả và tài liệu tham số để chọn công cụ và xây dựng tham số.

Ví dụ giả định cho công cụ GiftGenius trong máy chủ MCP TypeScript:

server.registerTool(
  "suggest_gifts",
  {
    title: "Suggest gifts",
    description: "Suggest 3–5 gift ideas based on recipient profile.",
    inputSchema: {
      type: "object",
      properties: {
        recipient: {
          type: "string",
          description: "Who is the gift for (e.g. mother, colleague)?",
        },
      },
      required: ["recipient"],
    },
  },
  async ({ input }) => { /* ... */ }
);

Hiện mọi thứ đều bằng tiếng Anh, mô hình hiểu rất rõ. Nhưng nếu người dùng viết bằng tiếng Việt thì sao? Nó vẫn có thể gắn “mẹ” với recipient, nhưng với các trường phức tạp và thuật ngữ miền hẹp, xác suất đi chệch tăng lên. Trong bài về chiến lược nội địa hóa mô tả, chúng ta sẽ bàn thêm: giữ một ngôn ngữ tiếng Anh thống nhất cho mô tả hay dùng mô tả đã nội địa hóa.

Ở giai đoạn này của bản đồ nội địa hóa, chỉ cần ghi chú: mô tả tools và JSON Schema cũng có thể được nội địa hóa, và điều này ảnh hưởng đến hành vi của mô hình.

Commerce và pháp lý

Cuối cùng là lớp hay bị nhớ tới vào phút chót — mọi thứ liên quan đến tiền bạc và văn bản pháp lý:

  • tên SKU và các gói thuê bao;
  • các trường title/description trong commerce feed (sản phẩm, dịch vụ, gói thuê bao);
  • Terms of Service, Privacy Policy, Refund Policy;
  • email và thông báo (email, push), nếu App gửi gì đó ra ngoài ChatGPT;
  • trạng thái đơn hàng và lỗi thanh toán mà bạn hiển thị cho người dùng (“Thanh toán bị từ chối”, “Không khả dụng ở khu vực của bạn”).

Có hai khía cạnh: UX và luật. Người dùng cần hiểu mình đang đồng ý điều gì và trả tiền cho cái gì bằng chính ngôn ngữ của họ. Đồng thời bản dịch phải chính xác về mặt pháp lý: đôi khi bộ phận pháp chế yêu cầu chỉ coi văn bản ở một ngôn ngữ (ví dụ tiếng Anh) là ràng buộc pháp lý, còn các bản dịch khác chỉ mang tính tham khảo.

Trong bản đồ nội địa hóa, nhất thiết đánh dấu nội dung commerce và pháp lý như một lớp riêng, vì nó thường cần quy trình khác (luật sư, tuân thủ, phê duyệt nội dung với marketing).

3. Độ sâu nội địa hóa: “cosmetic” vs “ngữ nghĩa”

Khi nói “nội địa hóa App”, hữu ích khi phân biệt hai cấp độ: cosmetic và ngữ nghĩa.

Nội địa hóa cosmetic

Cosmetic — là mọi thứ thay đổi diện mạo và khả năng đọc, nhưng hầu như không làm thay đổi hành vi hệ thống. Ví dụ:

  • dịch tiêu đề và nhãn trên nút;
  • dịch placeholders trong ô nhập;
  • thông điệp lỗi “gần gũi” hơn trong UI;
  • văn bản marketing trong widget được nội địa hóa.

Với các ứng dụng web truyền thống, nhiều khi dừng ở đây. Trong ChatGPT App, đây là phần quan trọng, nhưng chỉ là phần nổi của tảng băng.

Nội địa hóa ngữ nghĩa

Ngữ nghĩa — là những thứ làm thay đổi hành vi của mô hình và logic của App. Ở đây ngôn ngữ ảnh hưởng đến:

  • công cụ nào được mô hình chọn;
  • cách nó điền tham số cho công cụ;
  • dữ liệu nào được coi là “đúng” với người dùng đó.

Ví dụ về nội địa hóa ngữ nghĩa:

  • system‑prompt theo ngôn ngữ người dùng, thiết lập phong cách và quy tắc giao tiếp;
  • mô tả tools và các trường của chúng bằng ngôn ngữ người dùng đang giao tiếp;
  • các văn bản gợi ý/hướng dẫn khác nhau tùy theo bối cảnh văn hóa;
  • thiết lập định dạng ngày/tiền tệ ảnh hưởng đến parsing và generation (31.12.2025 vs 12/31/2025).

Nếu bạn chỉ nội địa hóa cosmetic mà không chạm tới ngữ nghĩa, App có thể trông có vẻ đã nội địa hóa, nhưng bên trong hành xử như một App “tiếng Anh”. Trong bản đồ nội địa hóa, nên đánh dấu rõ những phần tử nào là then chốt với hành vi mô hình.

Với GiftGenius, ví dụ như:

  • mô tả trường budget trong JSON Schema (“Budget in the user’s currency”) — ngữ nghĩa;
  • nhãn nút “Chọn quà tặng” — cosmetic (quan trọng cho UX, nhưng mô hình không thấy).

Giờ khi đã phân biệt cosmetic và ngữ nghĩa, hợp lý để trả lời câu hỏi: bạn muốn App hoạt động ở bao nhiêu ngôn ngữ.

4. Ứng dụng đơn ngữ vs đa ngữ

Trước khi vẽ bản đồ, cần xác định tham vọng: bạn làm App đơn ngữ hay hướng tới khán giả đa ngữ.

Ứng dụng đơn ngữ

Ứng dụng đơn ngữ — là khi bạn chủ động chỉ hỗ trợ một ngôn ngữ, ví dụ chỉ tiếng Anh.

Widget UI, prompts, mô tả công cụ và dữ liệu — tất cả cùng một ngôn ngữ. Điều này đơn giản hóa rất nhiều:

  • một codebase không phân nhánh theo ngôn ngữ;
  • một lược đồ danh mục (không có title_en, title_ru hay tương tự);
  • dễ bảo trì và kiểm thử.

Nhưng dĩ nhiên phạm vi người dùng bị giới hạn. Với ChatGPT App, điều đó còn có nghĩa: nếu người dùng đến với locale khác, ChatGPT vẫn có thể hiển thị App của bạn, nhưng nó phải liên tục “chuyển ngữ” giữa ngôn ngữ của người dùng và ngôn ngữ nội bộ của App. Ở một số ngách điều này ổn, nhưng với dịch vụ quà tặng tiêu dùng đại chúng — khó phù hợp.

Ứng dụng đa ngữ

Ứng dụng đa ngữ — là một quyết định mang tính kiến trúc. Ở đây:

  • UI và văn bản hiển thị đúng theo locale của người dùng;
  • dữ liệu (danh mục, mô tả sản phẩm) cũng gắn với ngôn ngữ/khu vực;
  • mô tả tools và system‑prompts có thể thay đổi theo ngôn ngữ;
  • các kịch bản commerce tính đến tiền tệ địa phương, thuế, hạn chế.

Trong trường hợp này, một vài dòng điều kiện kiểu if (locale === "ru") rải khắp code rõ ràng là không đủ. Cần một kiến trúc: từ điển, tài nguyên có thể nội địa hóa, một nơi thống nhất lưu và xử lý localeuserLocation, quy ước giữa widget và máy chủ MCP.

Tài liệu Apps SDK nhấn mạnh rằng ChatGPT truyền cho bạn localeuserLocation trong _meta khi gọi công cụ, để bạn có thể chọn đúng ngôn ngữ và định dạng dữ liệu ở phía máy chủ. Đây chính là “nhiên liệu” cho App đa ngữ.

So sánh nhỏ

Để trực quan — so sánh nhanh:

Đặc trưng Ứng dụng đơn ngữ Ứng dụng đa ngữ
Khối lượng mã Ít hơn Nhiều hơn (từ điển, logic lựa chọn)
Mức độ bao phủ người dùng Hạn chế Toàn cầu
Độ phức tạp kiểm thử Thấp hơn Cao hơn
Xử lý commerce/pháp lý Đơn giản hơn Cần quy trình và pháp chế
Xử lý hành vi GPT Prompt đơn ngữ Prompts/descriptions đa ngữ

Ở cấp độ khóa học, ta giả định GiftGenius sẽ trở thành đa ngữ (tối thiểu EN/RU) để minh họa sơ đồ “người lớn”. Nhưng nhiều mẹo vẫn hữu ích cho App đơn ngữ nếu bạn muốn sẵn sàng mở rộng.

5. Những nơi ngôn ngữ thực sự ảnh hưởng tới mô hình

Giờ hãy đánh dấu các điểm mà ngôn ngữ tác động trực tiếp đến hành vi của ChatGPT.

Ngôn ngữ đầu vào của người dùng vs ngôn ngữ mô tả tools

Giả sử:

  • người dùng viết: “Hãy chọn quà cho đồng nghiệp với ngân sách 50 euro”;
  • tool suggest_gifts của bạn chỉ được mô tả bằng tiếng Anh;
  • các trường của lược đồ: recipient, budget, currency, interests.

Mô hình cần:

  1. quyết định rằng cần gọi suggest_gifts;
  2. trích xuất recipient = "colleague", budget = 50, currency = "EUR";
  3. tuần tự hóa đúng cách thành các tham số JSON.

Nếu mô tả ngắn và ở ngôn ngữ khác, mô hình vẫn xử lý được, nhưng xác suất điền sai trường cao hơn. Ví dụ, nhầm budget với price_limit hoặc đưa văn bản vào trường interests, vì mô tả trường mơ hồ kiểu “Any extra info about the gift”.

Khi người dùng viết bằng tiếng Việt và mô tả bằng tiếng Anh, mô hình phải liên tục “nhảy” giữa hai ngôn ngữ.

Phương án với lược đồ đã nội địa hóa:

const locale = _meta?.["openai/locale"] ?? "en"; // được ChatGPT gửi kèm
const isRu = locale.startsWith("ru");

server.registerTool(
  "suggest_gifts",
  {
    title: isRu ? "Gợi ý quà tặng" : "Suggest gifts",
    description: isRu
      ? "Gợi ý 3–5 ý tưởng quà tặng dựa trên hồ sơ người nhận."
      : "Suggest 3–5 gift ideas based on recipient profile.",
    inputSchema: { /* ... */ },
  },
  async ({ input }) => { /* ... */ }
);

Đây là cách đơn giản hóa: trên thực tế mô tả nên được tạo một lần khi khởi động máy chủ, không phải mỗi lần gọi; nhưng ý tưởng là rõ. Ta có thể trả về cho ChatGPT các mô tả khác nhau tùy theo locale, để mô hình dễ hiểu người dùng hơn.

Ngôn ngữ dữ liệu vs ngôn ngữ yêu cầu

Nếu danh mục quà tặng của bạn chỉ có tiếng Anh, còn người dùng giao tiếp bằng tiếng Việt, mô hình sẽ chọn tên và mô tả bằng tiếng Anh. Đôi khi ổn, đôi khi không. Quan trọng hơn là cách bạn định dạng đầu ra:

  • bạn có hiển thị cho người dùng các title/description gốc từ máy chủ không;
  • hay mô hình tóm tắt lại bằng ngôn ngữ người dùng trong phần văn bản của nó;
  • hay tool của bạn tự trả về văn bản đã nội địa hóa dựa trên locale.

Trong Apps SDK, structured content (dữ liệu có cấu trúc được trả từ tools) và câu trả lời văn bản có thể sống tách biệt. Bạn có thể trả về dữ liệu có cấu trúc (ví dụ JSON các trường của sản phẩm) và một văn bản riêng cho người dùng, rồi mô hình quyết định cách render hay tóm tắt.

Nội địa hóa có thể diễn ra ở phía máy chủ (dữ liệu) hoặc ở phía mô hình (diễn đạt lại bằng ngôn ngữ cần thiết). Khi lập bản đồ, nên quyết định “điểm chốt” nằm ở đâu.

System‑prompt và follow‑ups

Nếu system‑prompt của bạn chỉ có tiếng Anh, còn người dùng nói tiếng Nga, mô hình sẽ phải cân bằng giữa hai ngôn ngữ. Đôi khi bình thường, nhưng đôi lúc bạn muốn đặt tông rõ ràng: ví dụ bản tiếng Việt muốn phong cách thân thiện hơn, còn bản tiếng Anh — trang trọng.

Vì vậy, trong bản đồ nội địa hóa cần đánh dấu:

  • system‑prompt EN;
  • system‑prompt RU;
  • các mẫu follow‑ups (EN/RU);
  • mọi gợi ý “cứng” trong prompt cho công cụ.

6. Bản đồ nội địa hóa cho GiftGenius

Giờ hãy gom tất cả những gì đã bàn về các lớp, độ sâu và ngôn ngữ thành một bản đồ nội địa hóa rõ ràng cho GiftGenius. Hãy làm điều mà sau này bạn sẽ làm cho App của mình: lập bản đồ nội địa hóa. Ý tưởng đơn giản: bảng với cột là lớp và kiểu thực thể, hàng là các phần tử cụ thể.

Ví dụ bản đồ

Đây là bản đồ rút gọn cho GiftGenius (EN/RU):

Danh mục Thành phần Ví dụ giá trị (EN) Ví dụ (VI) Cosmetic hay ngữ nghĩa
UI Tiêu đề widget GiftGenius: find a perfect present GiftGenius: chọn món quà hoàn hảo Cosmetic
UI Nhãn người nhận Recipient Người nhận Cosmetic
UI Lỗi danh sách trống No gifts found Không tìm thấy quà tặng Cosmetic
Prompts System‑prompt You are GiftGenius, a gift assistant… Bạn là GiftGenius, trợ lý chọn quà… Ngữ nghĩa
Prompts Mẫu tóm tắt lựa chọn Here’s why these gifts fit… Đây là lý do những món quà này phù hợp… Ngữ nghĩa
Data Tên quà tặng Smart mug Cốc thông minh Cả UX và ngữ nghĩa
Data Mô tả quà tặng Self‑heating mug with app control… Cốc tự làm nóng với điều khiển qua ứng dụng… Cả UX và ngữ nghĩa
Data Tiền tệ 59.99 USD 5 499 ₽ / 59,99 € Ngữ nghĩa (định dạng/tiền tệ)
Tools/schema
suggest_gifts.description
Suggest gift ideas based on profile… Gợi ý ý tưởng quà tặng dựa trên hồ sơ… Ngữ nghĩa
Tools/schema
budget.description
Budget in user’s currency Ngân sách theo đơn vị tiền tệ của người dùng Ngữ nghĩa
Commerce Tên SKU trong feed “Premium subscription – 1 year” “Gói Premium – 1 năm” Cả UX và pháp lý
Commerce Trang Terms Terms of Service (EN only) Thông báo: chỉ văn bản EN có giá trị pháp lý Ngữ nghĩa/pháp lý
Errors (backend) Thông báo lỗi thanh toán Payment failed, please try again later Thanh toán không thành công, vui lòng thử lại sau Cosmetic + UX

Bên trái là nhóm theo lớp, tiếp theo là các phần tử cụ thể. Cột cuối giúp hiểu những gì không thể chỉnh mà không có sự đồng thuận của người thiết kế prompt/kỹ sư mô hình: mọi thứ được đánh dấu là ngữ nghĩa đều ảnh hưởng tới hành vi GPT.

Phác thảo mã nhỏ

Để liên kết bản đồ với mã, có thể tạo một kiểu đơn giản cho các thực thể có thể nội địa hóa:

type LocalizedTextKey =
  | "ui.title"
  | "ui.recipient_label"
  | "error.no_gifts"
  | "prompt.summary_intro";

type Locale = "en" | "ru";

type Messages = Record<Locale, Record<LocalizedTextKey, string>>;
const messages: Messages = {
  en: {
    "ui.title": "GiftGenius: find a perfect present",
    "ui.recipient_label": "Recipient",
    "error.no_gifts": "No gifts found",
    "prompt.summary_intro": "Here’s why these gifts fit:",
  },
  ru: {
    "ui.title": "GiftGenius: chọn món quà hoàn hảo",
    "ui.recipient_label": "Người nhận",
    "error.no_gifts": "Không tìm thấy quà tặng",
    "prompt.summary_intro": "Đây là lý do những món quà này phù hợp:",
  },
};

Sau đó các khóa này có thể dùng cả ở widget lẫn khi tạo prompts trên máy chủ (miễn là bạn truyền locale xuyên suốt stack — sẽ bàn ở bài tiếp theo). Như vậy “bản đồ nội địa hóa” dần trở thành một từ điển có kiểu, thay vì một tập hợp chuỗi rời rạc.

7. Thực hành: lập bản đồ nội địa hóa cho App của bạn

Trước khi đi sâu vào kỹ thuật i18n và kiến trúc Gateway/MCP, hãy làm một bài tập hơi “nhàm chán” nhưng rất hữu ích: mô tả trung thực bạn định nội địa hóa những gì.

Cách tốt: mở bất kỳ trình soạn thảo nào (Google Sheets hay Notion đều được) và lập bảng với các cột:

  • danh mục/lớp (UI, prompts, dữ liệu, tools, commerce và pháp lý, lỗi);
  • phần tử (nút cụ thể, mô tả trường cụ thể, endpoint cụ thể có văn bản);
  • ví dụ giá trị EN;
  • ví dụ giá trị ở ngôn ngữ thứ hai (nếu đã có hoặc bản nháp);
  • đánh dấu “cosmetic/ngữ nghĩa/quan trọng pháp lý”;
  • chủ sở hữu (ai chịu trách nhiệm sửa: frontend, máy chủ MCP, product, pháp chế).

Sau đó đi qua App của bạn và liệt kê trung thực mọi nơi có văn bản hoặc nơi ngôn ngữ ảnh hưởng đến định dạng dữ liệu.

Với GiftGenius, kết quả sẽ là bản mở rộng của bảng ở trên. Trên đường làm, bạn gần như chắc chắn phát hiện vài chỗ “ẩn”:

  • các hằng văn bản trong mã máy chủ MCP (ví dụ thông điệp lỗi);
  • giá trị mặc định trong structuredContent (ví dụ danh mục bạn không hiển thị trong UI);
  • nhãn cũ ở tools, không còn tương ứng với hành vi thực tế.

Bài tập này đặc biệt hữu ích khi làm trước khi bạn nối nội địa hóa với quy trình kinh doanh thực (thanh toán, kích hoạt thuê bao, tài liệu pháp lý). Sau này đổi tên tool charge_user trong hệ thống đa ngữ có ACP và văn bản pháp lý sẽ đau đầu hơn nhiều.

Tóm lại, nếu bạn vẽ bản đồ nội địa hóa từ sớm và trung thực đánh dấu những gì sẽ hỗ trợ ở ngôn ngữ nào, bạn sẽ tiết kiệm rất nhiều công sức ở các mô-đun tiếp theo — khi MCP, Gateway, commerce và Store tham gia cuộc chơi.

8. Các lỗi thường gặp khi lên kế hoạch nội địa hóa

Lỗi số 1: nghĩ rằng nội địa hóa = “dịch các nút”.
Kịch bản rất phổ biến: đội ngũ cẩn thận đưa mọi chuỗi UI vào từ điển, dịch chúng và hài lòng. Trong khi đó system‑prompt vẫn chỉ tiếng Anh, mô tả tools cũng vậy, còn danh mục sản phẩm chỉ có tên tiếng Anh. Kết quả App trông có vẻ đã nội địa hóa, nhưng mô hình bên trong vẫn “sống” trong thế giới riêng, và hành vi vẫn thiên về tiếng Anh. Trên thực tế điều này thể hiện ở khuyến nghị kỳ lạ và lỗi trong các tham số tools.

Lỗi số 2: không phân biệt cosmetic và ngữ nghĩa.
Đôi khi product yêu cầu “chỉnh nhẹ câu chữ” trong mô tả công cụ hoặc system‑prompt, và lập trình viên sửa văn bản như thể đó là nhãn UI đơn giản. Nhưng mô tả trường JSON Schema hoặc một câu trong system‑prompt là một phần hợp đồng với mô hình. Những thay đổi này có thể làm GPT gọi công cụ của bạn theo cách rất khác. Nếu không đánh dấu sẵn các phần tử ngữ nghĩa trong bản đồ nội địa hóa, rất dễ vô tình làm hỏng hành vi App.

Lỗi số 3: bắt đầu đa ngữ một cách hỗn loạn, không có kiến trúc.
Rất dễ bị cám dỗ lúc đầu chỉ cần rải vài dòng if (locale === "ru") và thay chuỗi tiếng Việt ở chỗ cần. Kết quả sau vài tuần ứng dụng trở thành “địa ngục nội địa hóa”: ở một component chuỗi từ điển, ở component khác lại hardcode trong JSX, trên máy chủ — một sơ đồ đặt tên khóa khác. Sau này gắn hệ thống i18n chuẩn và đưa mọi thứ về một kiểu chung sẽ khó hơn nhiều.

Lỗi số 4: quên dữ liệu và tiền bạc.
Ngay cả đội ngũ giàu kinh nghiệm cũng thường bắt đầu từ dịch UI và prompts, nhưng quên rằng danh mục sản phẩm, giá, tiền tệ và văn bản pháp lý cũng phải xét tới locale và userLocation. Trong đặc tả product feed cho ChatGPT, các trường văn bản và giá được quy định rõ để hiển thị đúng cho người dùng. Nếu bạn không thiết kế đa ngữ ở tầng dữ liệu, sau này sẽ phải nhân đôi feed hoặc làm các migration đau đớn.

Lỗi số 5: bỏ qua tín hiệu của nền tảng về locale và vị trí.
ChatGPT đã truyền trong các lời gọi MCP _meta["openai/locale"]_meta["openai/userLocation"], để bạn hiểu đang giao tiếp bằng ngôn ngữ nào và từ khu vực nào. Một số nhà phát triển vẫn yêu cầu người dùng “Chọn ngôn ngữ giao diện” ngay lần đầu và không sử dụng các tín hiệu này để chọn tài nguyên và giá. Hệ quả là UX kém và kiến trúc phức tạp hơn mức cần thiết.

Lỗi số 6: không xác định “chủ sở hữu” của các phần tử có thể nội địa hóa.
Khi vào vận hành, các bản dịch bị phân tán: frontend sửa văn bản UI, backend sửa mô tả tools, chuyên gia ML sửa system‑prompt, còn pháp chế gửi lại nội dung Terms đã chỉnh. Nếu trong bản đồ nội địa hóa không chỉ rõ ai phụ trách lớp nào, thay đổi sẽ va chạm, có văn bản được cập nhật ở nơi này mà không được cập nhật ở nơi khác.

Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION