Creation:2025-09-22Last update:2026-01-26

    Intlayer v8. Có gì mới?

    Chào mừng đến với Intlayer v8! Bản phát hành này tập trung vào nâng cao trải nghiệm nhà phát triển với phát hiện nội dung tự động, đảm bảo tính toàn vẹn dữ liệu bằng xác thực theo schema và cung cấp nhiều khả năng kiểm soát hơn đối với quản lý từ điển.

    www.youtube.com

    Mục lục


    Sự tiến hóa của nội dung phong phú: Markdown & HTML

    Intlayer v8 mang đến những cải tiến lớn về cách xử lý nội dung phong phú, giới thiệu nút HTML (không tồn tại trong v7) và hợp nhất API với nút Markdown (đã tồn tại trong v7 nhưng được nâng cao).

    API .use() hợp nhất

    Chúng tôi đã giới thiệu phương thức .use() cho cả nút Markdown và HTML. Phương thức này cho phép bạn tùy chỉnh các thẻ HTML hoặc các component được sử dụng trong quá trình render.

    • Thay thế component: Bạn có thể dễ dàng thay thế các thẻ HTML hoặc các component tùy chỉnh bằng các component framework của riêng bạn (ví dụ: thay thế <a> bằng NextLink hoặc <CustomCmp> bằng một component React).
    • An toàn kiểu dữ liệu (Type Safety): Tất cả các hàm cung cấp component đều được định kiểu đầy đủ, đảm bảo bạn nhận được các props chính xác.

    Hành vi render mặc định

    Trong v7, nếu không có provider nào được xác định, các nút Markdown sẽ được render dưới dạng chuỗi thô, thường yêu cầu các thư viện bên ngoài để phân tích cú pháp.

    Trong v8, Intlayer bao gồm trình phân tích cú pháp Markdown nội bộ của riêng mình. Theo mặc định, các nút Markdown hiện được render trực tiếp dưới dạng HTML mà không cần bất kỳ thư viện bên ngoài nào.

    Các tiện ích Renderer & Provider mới

    Chúng tôi đã giới thiệu các hàm renderer và component độc lập mới để cung cấp cho bạn nhiều quyền kiểm soát hơn bên ngoài luồng useIntlayer tiêu chuẩn.

    • Markdown: MarkdownRenderer, useMarkdownRenderer, renderMarkdown. (Lưu ý: MarkdownProvider đã tồn tại trong v7 nhưng hiện tích hợp với các công cụ mới này).
    • HTML: HTMLRenderer, useHTMLRenderer, renderHTML, HTMLProvider.

    Ví dụ: Công cụ render Markdown

    1. Sử dụng Thành phần (Component):

    tsx
    import { MarkdownRenderer } from "react-intlayer/markdown";<MarkdownRenderer  forceBlock={true}  components={{    h1: ({ children }) => <h1 className="text-2xl">{children}</h1>  }}>  {"# My Title"}</MarkdownRenderer>

    2. Sử dụng Hook:

    tsx
    import { useMarkdownRenderer } from "react-intlayer/markdown";const renderMarkdown = useMarkdownRenderer({  components: {    h1: ({ children }) => <h1 className="text-red-500">{children}</h1>  }});return <div>{renderMarkdown("# My Title")}</div>;

    3. Sử dụng Hàm tiện ích:

    tsx
    import { renderMarkdown } from "react-intlayer/markdown";const html = renderMarkdown("# My Title", {  forceBlock: true});

    Ví dụ: Công cụ render HTML

    1. Sử dụng Thành phần (Component):

    tsx
    import { HTMLRenderer } from "react-intlayer/html";<HTMLRenderer  components={{    p: ({ children }) => <p className="mb-4">{children}</p>  }}>  {"<p>Hello World</p>"}</HTMLRenderer>

    2. Sử dụng Hook:

    tsx
    import { useHTMLRenderer } from "react-intlayer/html";const renderHTML = useHTMLRenderer({  components: {    strong: ({ children }) => <b className="font-bold">{children}</b>  }});return <div>{renderHTML("<p>Hello <strong>World</strong></p>")}</div>;

    3. Sử dụng Hàm tiện ích:

    tsx
    import { renderHTML } from "react-intlayer/html";const html = renderHTML("<p>Hello World</p>");

    Để biết thêm chi tiết, xem Tài liệu Nội dung HTMLTài liệu Markdown.


    Viết lại URL tùy chỉnh

    Intlayer v8 giới thiệu hỗ trợ cho Viết lại URL tùy chỉnh, cho phép bạn định nghĩa các đường dẫn theo ngôn ngữ (locale) khác với cấu trúc chuẩn /locale/path. Đây là một tính năng mạnh mẽ để cải thiện SEO địa phương và mang lại trải nghiệm người dùng tự nhiên hơn cho những người không nói tiếng Anh.

    Các cải tiến chính trong v8:

    • Bộ định dạng cho framework: Thêm nextjsRewrite, svelteKitRewrite, reactRouterRewrite, vueRouterRewrite, solidRouterRewrite, tanstackRouterRewrite, nuxtRewrite, và viteRewrite để cung cấp cú pháp mẫu đặc trưng cho từng router.
    • Hook useRewriteURL: một hook phía client mới tự động chỉnh sửa thanh địa chỉ thành URL địa phương "đẹp" mà không kích hoạt điều hướng của router.
    • Chuyển hướng SEO tự động: Các proxy tích hợp bây giờ tự động chuyển hướng người dùng từ các đường dẫn chuẩn được gõ thủ công (ví dụ: /fr/about) sang các phiên bản địa phương "đẹp" hơn của chúng (ví dụ: /fr/a-propos).

    Cấu hình ví dụ:

    intlayer.config.ts
    import { Locales, type IntlayerConfig } from "intlayer";import { nextjsRewrite } from "intlayer/routing";const config: IntlayerConfig = {  internationalization: {    locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],    defaultLocale: Locales.ENGLISH,  },  routing: {    mode: "prefix-no-default",    rewrite: nextjsRewrite({      "/[locale]/about": {        fr: "/[locale]/a-propos",        es: "/[locale]/acerca-de",      },      "/[locale]/products/[id]": {        fr: "/[locale]/produits/[id]",        es: "/[locale]/productos/[id]",      },    }),  },};export default config;

    Tính năng này được hỗ trợ sẵn (out-of-the-box) trong Next.jsVite thông qua các proxies của Intlayer, và có thể dễ dàng tích hợp vào các router khác như TanStack Router, React Router, Vue Router, SvelteKit, và Solid Router.

    Để biết thêm thông tin và hướng dẫn tích hợp, xem Tài liệu Viết lại URL tùy chỉnh.


    Giá trị insertion được cải tiến

    Trong v8, các giá trị insertion bây giờ có thể chấp nhận React elements (hoặc Vue nodes) bên cạnh chuỗi và số. Điều này cho phép bạn chèn các thành phần phong phú và tương tác trực tiếp vào các mẫu insertion của mình.

    Intlayer hiện xử lý mạnh mẽ các node React và Preact lồng nhau trong các insertions, đảm bảo các cấu trúc UI phức tạp được giữ nguyên và kết xuất đúng.

    Ví dụ:

    src/example.content.ts
    import { insert } from "intlayer";export default {  key: "my-key",  content: {    myInsertion: insert("Hi {{name}}"),  },};
    tsx
    import { useIntlayer } from "next-intlayer";const { myInsertion } = useIntlayer("my-key");return (  <div>    {myInsertion({      name: 2, // số      // hoặc      name: "John", // chuỗi      // hoặc      name: <span>John</span>, // phần tử React    })}  </div>);

    Xác thực Schema Nội dung

    Intlayer v8 giới thiệu tính năng xác thực schema cho các dictionaries. Bây giờ bạn có thể định nghĩa các schema xác thực có thể tái sử dụng trong cấu hình của mình bằng Zod và áp dụng chúng cho các file nội dung. Điều này đảm bảo nội dung của bạn luôn tuân theo cấu trúc mong đợi, giúp phát hiện lỗi trong quá trình build.

    1. Định nghĩa Schema

    Định nghĩa các schema trong intlayer.config.ts:

    intlayer.config.ts
    import { z } from "zod";export default {  schemas: {    "seo-metadata": z.object({      title: z.string().min(50).max(60),      description: z.string().min(150).max(160),    }),  },};

    2. Áp dụng Schema cho các Dictionaries

    Tham chiếu khóa schema trong định nghĩa dictionary của bạn:

    src/example.content.ts
    import { type Dictionary } from "intlayer";const aboutPageMetaContent = {  key: "about-page-meta",  schema: "seo-metadata", // <--  content: {    title: "About Our Company - Learn More About Us",    description: "Discover our company's mission, values, and team.",  },} satisfies Dictionary;export default aboutPageMetaContent;

    Nếu nội dung không khớp với schema (ví dụ: title quá ngắn), quá trình build sẽ báo lỗi.


    Phát hiện nội dung tự động nâng cao

    Trong v8, Intlayer tự động nhận diện thông minh cú pháp Markdown, thẻ HTML và các chèn biến trong các chuỗi nội dung của bạn. Điều này có nghĩa là bạn thường có thể bỏ qua các hàm trợ giúp như md(), html() hoặc insert().

    Hành vi này được bật theo mặc định. Bạn có thể tinh chỉnh việc phát hiện này toàn cục trong intlayer.config.ts hoặc cho từng dictionary.

    Kiểm soát chi tiết

    Bạn có thể bật hoặc tắt các loại chuyển đổi cụ thể:

    intlayer.config.ts
    export default {  dictionary: {    // contentAutoTransformation: false (mặc định)    contentAutoTransformation: {      markdown: true,      html: true,      insertion: false, // Vô hiệu hóa phát hiện tự động cho insertion    },  },};

    Hành vi v7 (Bao bọc thủ công):

    src/example.content.ts
    import { md, insert } from "intlayer";export default {  key: "my-key",  content: {    myMarkdown: md("## Hello World"),    myInsertion: insert("Hi {{name}}"),  },};

    Hành vi v8 (Phát hiện tự động):

    src/example.content.ts
    export default {  key: "my-key",  contentAutoTransformation: true, // Có thể cũng được đặt bởi định nghĩa dictionary hoặc toàn cục trong intlayer.config.ts  content: {    myMarkdown: "## Xin chào Thế giới", // Tự động được phát hiện là Markdown    myHTML: "<p>Xin chào Thế giới</p>", // Tự động được phát hiện là HTML    myInsertion: "Chào {{name}}", // Tự động được phát hiện là Insertion  },};

    The underlying JSON result remains the same, preserving the rich type information needed for rendering:

    json
    {  "key": "my-key",  "content": {    "myMarkdown": {      "nodeType": "markdown",      "markdown": "## Xin chào Thế giới"    },    "myHTML": {      "nodeType": "html",      "html": "<p>Xin chào Thế giới</p>"    },    "myInsertion": {      "nodeType": "insertion",      "insertion": "Hi {{name}}"    }  }}

    Địa phương hóa: hook useIntl mới

    Một hook useIntl() mới hiện có sẵn trong React, Next.js và Vue. Nó cung cấp một đối tượng Intl liên kết với locale, tự động sử dụng ngôn ngữ hiện tại để định dạng số, ngày tháng và nhiều thứ khác, mà không cần phải truyền thủ công locale.

    tsx
    import { useIntl } from "next-intlayer";const intl = useIntl();const formattedPrice = new intl.NumberFormat({  style: "currency",  currency: "USD",}).format(123.45);

    Công cụ: Cải tiến Extension VSCode

    Phần mở rộng Intlayer cho VSCode nhận được các cập nhật lớn trong v8 nhằm hợp lý hóa quy trình làm việc về quốc tế hóa của bạn:

    • Thời gian khởi động: Cải thiện hiệu suất khi mở một dự án.
    • Bộ nhớ đệm: Tầng caching được nâng cấp để xác thực và gợi ý tự động gần như tức thì.
    • Phát hiện Khóa Không Sử dụng & Khóa Trùng Lặp: Các tính năng mới để tự động phát hiện khóa không sử dụngkhóa trùng lặp trong các từ điển của bạn, giúp giữ nội dung gọn gàng và hiệu quả.

    Tối ưu trình biên dịch

    Intlayer v8 bao gồm một lớp cache mới cho trình biên dịch Markdown và HTML. Điều này đảm bảo rằng các chuỗi nội dung giống hệt với cùng cấu hình chỉ được phân tích một lần, giảm đáng kể chi phí khi tái kết xuất hoặc khi sử dụng cùng nội dung ở nhiều nơi.

    babel.config.js
      const {  intlayerExtractBabelPlugin,  intlayerOptimizeBabelPlugin,  getExtractPluginOptions,  getOptimizePluginOptions,} = require('@intlayer/babel');module.exports = {  presets: ['next/babel'],  plugins: [    // Trích xuất nội dung từ components vào dictionaries    [intlayerExtractBabelPlugin, getExtractPluginOptions()],    // Tối ưu các imports bằng cách thay thế useIntlayer bằng import trực tiếp các dictionary    [intlayerOptimizeBabelPlugin, getOptimizePluginOptions()],  ],};

    Tính linh hoạt: Chế độ import hợp nhất

    Thuộc tính boolean live đã bị đánh dấu là deprecated và được thay bằng thuộc tính importMode toàn diện hơn. Điều này cho phép xác định rõ ràng cách các dictionary nên được tải: theo kiểu tĩnh, động, hoặc qua đồng bộ trực tiếp.

    Các chế độ

    • static (Mặc định): Dictionary được đóng gói tại thời điểm build. Tối ưu cho hiệu năng.
    • dynamic: Dictionary được tải vào thời điểm runtime (ví dụ: thông qua fetch JSON hoặc suspense).
    • fetch: Dictionary được lấy từ CMS/Server vào thời điểm runtime và được đồng bộ.

    Di chuyển:

    Cấu hình v7 Cấu hình v8
    live: true importMode: 'fetch'
    live: false importMode: 'static' (hoặc 'dynamic')

    Lưu ý: Trong Intlayer v8, thuộc tính importMode đã được chuyển từ cấu hình build sang cấu hình dictionary trong intlayer.config.ts. Điều này cho phép bạn định nghĩa chế độ import mặc định cho tất cả các dictionary trong khi vẫn có thể ghi đè cho từng dictionary riêng lẻ.

    Ví dụ Cấu hình Toàn cục:

    intlayer.config.ts
    export default {  dictionary: {    importMode: "dynamic", // Mặc định toàn cục  },  // ...};

    Ví dụ Dictionary:

    src/example.content.ts
    export default {    key: 'my-key',    importMode: "fetch", // Ghi đè cấu hình toàn cục    content: { ... }}

    Kiểm soát vị trí Dictionary

    v8 giới thiệu thuộc tính location để quản lý rõ ràng nơi lưu trữ các dictionary và cách chúng đồng bộ hóa. Điều này đặc biệt hữu ích cho các luồng công việc hybrid liên quan đến cả file cục bộ và nội dung CMS từ xa.

    Tùy chọn

    • local: Từ điển chỉ tồn tại cục bộ. Nó sẽ không được đẩy lên CMS từ xa.
    • remote: Từ điển được quản lý từ xa. Khi đã được đẩy lên CMS, nó sẽ tách rời khỏi bản cục bộ. Từ điển từ xa sẽ được kéo từ CMS.
    • local_and_remote: Từ điển tồn tại ở cả hai nơi. Thay đổi cục bộ được đẩy lên, và thay đổi từ xa được kéo về (đồng bộ hóa).

    Ví dụ:

    src/example.content.ts
    export default {    key: 'my-key',    location: "local", // Giữ từ điển này chỉ ở cục bộ    content: { ... }}

    Phân tách Cấu hình Hệ thống

    Intlayer v8 tách cấu hình các nguồn nội dung khỏi các đường dẫn hệ thống nội bộ và đường dẫn đầu ra. Điều này làm gọn thuộc tính content và làm rõ những thiết lập nào dành cho quản lý bởi người dùng so với những thiết lập được quản lý bởi hệ thống Intlayer.

    Các thuộc tính sau đã được chuyển từ content sang thuộc tính system mới trong intlayer.config.ts:

    • dictionariesDir
    • moduleAugmentationDir
    • unmergedDictionariesDir
    • typesDir
    • mainDir
    • configDir
    • cacheDir
    • outputFilesPatternWithPath

    Hành vi v7:

    intlayer.config.ts
    export default {  content: {    contentDir: ["src"],    dictionariesDir: ".intlayer/dictionary", // Bị trộn với cấu hình nguồn  },};

    Hành vi v8:

    intlayer.config.ts
    export default {  content: {    contentDir: ["src"],  },  system: {    dictionariesDir: ".intlayer/dictionary", // Được tách riêng rõ ràng  },};

    Tách thư mục nội dung và mã nguồn

    Intlayer v8 tách cấu hình cho các tệp định nghĩa nội dung khỏi cấu hình cho chuyển đổi mã. Điều này cho phép việc theo dõi và quét chính xác hơn, cải thiện hiệu năng build.

    Trước đây, contentDir được sử dụng cho cả việc theo dõi các tệp .content.* và quét mã để tìm các lời gọi useIntlayer. Hiện nay:

    • contentDir: Dành riêng cho các tệp khai báo nội dung của bạn.
    • codeDir: Dành riêng cho mã ứng dụng của bạn cần chuyển đổi (ví dụ: pruning, optimization).

    Di chuyển:

    Nếu trước đây bạn đã thiết lập contentDir, Intlayer v8 sẽ sử dụng nó làm mặc định cho codeDir nhưng sẽ ghi một cảnh báo. Bạn nên định nghĩa rõ codeDir trong cấu hình của mình.

    Hành vi v7:

    intlayer.config.ts
    export default {  content: {    contentDir: ["src", "@packages/design-system"], // Được sử dụng cho cả content và code  },};

    Hành vi v8:

    intlayer.config.ts
    export default {  content: {    contentDir: ["src/content", "@packages/design-system"], // Chỉ theo dõi các file src/content/*.content.* ở đây và các file @packages/design-system/dist/*.content.*    codeDir: ["src", "@packages/design-system"], // Chỉ quét để biến đổi mã ở đây  },};

    Framework: Cải tiến cho Svelte

    Nội dung Markdown và HTML trong Svelte bây giờ tự động được phân tích cú pháp thành HTML khi được chuyển thành chuỗi. Điều này khiến việc sử dụng với cú pháp {@html} của Svelte dễ dàng hơn nhiều, vì bạn giờ có thể truyền trực tiếp node nội dung.


    Ghi chú nâng cấp từ v7

    Thay đổi cấu hình

    • live property: Thuộc tính live trong các dictionary đã bị xóa. Hãy sử dụng importMode: 'fetch' thay thế.
    • importMode: Thuộc tính build.importMode trong cấu hình đã bị đánh dấu là không còn được khuyến khích. Hãy sử dụng dictionary.importMode thay thế.
    • contentDircodeDir: contentDir hiện được dùng riêng cho các tệp nội dung. Một thuộc tính mới codeDir đã được thêm để chuyển đổi mã. Nếu codeDir không được thiết lập, Intlayer sẽ fallback về contentDir và ghi log một cảnh báo.
    • Xác thực Schema: Để sử dụng tính năng schema mới, đảm bảo bạn đã cài zod trong dự án của mình.

    Liên kết hữu ích