Đặt câu hỏi và nhận tóm tắt tài liệu bằng cách tham chiếu trang này và nhà cung cấp AI bạn chọn
Lịch sử phiên bản
- "Sử dụng middleware và hook remix-intlayer"v9.5.519/9/2026
- "Tài liệu ban đầu cho Remix 3"v9.5.09/9/2026
Nội dung của trang này đã được dịch bằng AI.
Xem phiên bản mới nhất của nội dung gốc bằng tiếng AnhNếu bạn có ý tưởng để cải thiện tài liệu này, vui lòng đóng góp bằng cách gửi pull request trên GitHub.
Liên kết GitHub tới tài liệuSao chép Markdown của tài liệu vào bộ nhớ tạm
Dịch trang web Remix 3 của bạn bằng Intlayer
Hướng dẫn này minh họa cách tích hợp Intlayer để quốc tế hóa liền mạch trong các ứng dụng Remix 3 với định tuyến theo ngôn ngữ, khai báo nội dung an toàn kiểu dữ liệu, các thành phần JSX kết xuất phía máy chủ và hỗ trợ đa môi trường thực thi trên Node.js, Bun, Deno và Cloudflare Workers.
Remix 3 là gì?
Remix 3 đại diện cho một bước chuyển đổi kiến trúc cơ bản hướng tới một framework web có thể kết hợp, độc lập với môi trường chạy (runtime-agnostic) và được xây dựng hoàn toàn dựa trên các tiêu chuẩn web. Thay vì gắn liền với các công cụ đóng gói cụ thể hoặc API máy chủ độc quyền, Remix 3 được phân phối dưới dạng các gói đơn nhiệm có thể kết hợp:
remix/fetch-router(hoặcremix/router): Định tuyến nhẹ, tuân thủ tiêu chuẩn dựa trên Fetch API (RequestvàResponse).remix/ui: Mô hình thành phần JSX (jsxImportSource: "remix/ui"). Một thành phần là một hàm thiết lập (setup function) trả về một hàm kết xuất (render function), nhận props qua một handle có định kiểu.remix/middleware/render: Cài đặtcontext.render(<Page />)trên mỗi yêu cầu, truyền phát (streaming) cây JSX sang mộtResponseHTML.remix/node-fetch-server: Bộ điều hợp máy chủ cho Node.js, hỗ trợ nguyên bản cho Bun, Deno và các môi trường edge.remix/cookie: Phân tích cú pháp và tuần tự hóa cookie được ký bằng mật mã.
Kết hợp với Intlayer và gói remix-intlayer, một middleware ngôn ngữ cùng các hook useIntlayer / useDictionary / useLocale tương tự như react-intlayer, được liên kết với ngữ cảnh yêu cầu Remix, bạn sẽ có một hệ thống quốc tế hóa hoàn chỉnh mang lại sự an toàn kiểu tại thời điểm biên dịch, bản dịch AI tự động, kết xuất máy chủ không tốn chi phí và định tuyến ngôn ngữ mượt mà.
Mục lục
Tại sao nên chọn Intlayer thay vì các giải pháp khác?
So với các giải pháp truyền thống như i18next hoặc các trình tải bản dịch tùy chỉnh, Intlayer mang lại trải nghiệm nhà phát triển tích hợp được tối ưu hóa cho kiến trúc web hiện đại:
Intlayer được xây dựng để hoạt động liền mạch với các tiêu chuẩn web (Request, Response, Headers và URL). remix-intlayer cắm vào bộ định tuyến Fetch của Remix 3 dưới dạng một middleware nhẹ, trích xuất ngôn ngữ từ đường dẫn URL, cookie hoặc tiêu đề Accept-Language và hiển thị nó cho phần còn lại của yêu cầu, trình xử lý, chế độ xem và thành phần remix/ui, mà không cần truyền thủ công hay ràng buộc bạn vào một runtime cụ thể.
Tạm biệt các khóa JSON lỏng lẻo và các sự cố thiếu khóa khi chạy. Intlayer thực thi kiểm tra TypeScript trên tất cả các ngôn ngữ được khai báo, cảnh báo bạn ngay tại thời điểm xây dựng nếu bản dịch bị thiếu hoặc không hợp lệ.
Khi sử dụng các thành phần JSX kết xuất phía máy chủ của Remix 3, chỉ văn bản đã phân giải cho ngôn ngữ được yêu cầu mới được ghi vào luồng xuất. Các thành phần chạy hoàn toàn trên máy chủ trừ khi bạn cấu hình rõ ràng việc hydrat hóa phía máy khách thông qua clientEntry. Theo mặc định, không có danh mục dịch hay môi trường chạy hydrat hóa nào được gửi tới máy khách.
Intlayer sắp xếp các khai báo nội dung (.content.ts) cùng với logic định tuyến của bạn, giảm ngữ cảnh mã thông báo (token) cần thiết cho các Mô hình Ngôn ngữ Lớn (LLM). Các lệnh CLI tích hợp như intlayer fill và intlayer test cho phép bạn tự động hóa việc dịch trong các quy trình CI/CD với chi phí trực tiếp từ nhà cung cấp AI của bạn.
Vượt ra ngoài quy trình làm việc ưu tiên mã nguồn, Intlayer cung cấp một Trình biên tập trực quan tự lưu trữ và một CMS từ xa, cho phép các biên tập viên và dịch giả cập nhật nội dung mà không cần triển khai lại mã.
Hướng dẫn từng bước
Xem Mẫu ứng dụng trên GitHub.
Cài đặt các gói phụ thuộc
Cài đặt
intlayer,remix-intlayervàremix(phiên bản 3) bằng trình quản lý gói ưa thích của bạn:bashSao chép mãSao chép mã vào clipboard
intlayer: Công cụ quốc tế hóa cốt lõi cung cấp quản lý cấu hình, khai báo từ điển (t(),Dictionary), các công cụ CLI và trình thông dịch lúc chạy.remix-intlayer: Tích hợp Remix 3: middleware bộ định tuyếnintlayer()phân giải ngôn ngữ của mỗi yêu cầu, và các hookuseIntlayer,useDictionaryvàuseLocaleđọc ngôn ngữ đó ở bất kỳ vị trí nào phía sau.remix: Gói khung thống nhất Remix 3 xuất raremix/router,remix/routes,remix/ui,remix/middleware/rendervàremix/node-fetch-server.
Cấu hình Intlayer
Kiến trúc
Trong kiến trúc này, middleware
intlayer()củaremix-intlayerđược đăng ký trongcreateRouter()trước middlewarerender(). Nó loại bỏ tiền tố locale trước khi router khớp, do đó các route chỉ được khai báo một lần trongsrc/routes.tsmà không có phân đoạn:locale, đồng thời chạy phần còn lại của yêu cầu bên trong phạm viAsyncLocalStorage, cho phépuseIntlayer/useLocaleđọc locale mà không cần đối số trong các trình xử lý route và viewremix/ui. Các khai báo nội dung được đặt cùng với các view của bạn trongsrc/:bashSao chép mãSao chép mã vào clipboard
Cấu hình
Tạo tệp
intlayer.config.tstrong thư mục gốc của dự án để khai báo các ngôn ngữ được hỗ trợ và cài đặt quốc tế hóa:intlayer.config.tsSao chép mãSao chép mã vào clipboard
import { Locales, type IntlayerConfig } from "intlayer"; const config: IntlayerConfig = { internationalization: { locales: [ Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH, Locales.VIETNAMESE, ], defaultLocale: Locales.ENGLISH, }, }; export default config;Để biết thêm các tùy chọn cấu hình bổ sung, hãy tham khảo tài liệu cấu hình.
Khai báo nội dung đa ngôn ngữ
Khai báo nội dung đã dịch của bạn trong tệp
.content.ts:src/home.content.tsSao chép mãSao chép mã vào clipboard
import { t, type Dictionary } from "intlayer"; const homeContent = { key: "home", content: { title: t({ vi: "Chào mừng bạn đến với Remix 3", en: "Welcome to Remix 3", fr: "Bienvenue sur Remix 3", es: "Bienvenido a Remix 3", }), description: t({ vi: "Một ứng dụng theo tiêu chuẩn web, có thể kết hợp với tính năng i18n nguyên bản.", en: "A composable, web-standard application with native i18n.", fr: "Une application composable basée sur les standards web avec i18n native.", es: "Una aplicación componible basada en estándares web con i18n nativa.", }), switchLanguage: t({ vi: "Đổi ngôn ngữ:", en: "Switch language:", fr: "Changer de langue :", es: "Cambiar idioma:", }), }, } satisfies Dictionary; export default homeContent;Intlayer cũng hỗ trợ các định dạng JSON, YAML và CommonJS. Xem Tài liệu Khai báo Nội dung.
Xây dựng từ điển Intlayer
Biên dịch các định nghĩa từ điển để tạo các kiểu TypeScript và sổ đăng ký runtime:
bashSao chép mãSao chép mã vào clipboard
Thao tác này sẽ biên dịch nội dung của bạn vào thư mục tạo phẩm
.intlayer, cho phép tự động hoàn thành TypeScript đầy đủ và tra cứu từ điển nhanh chóng.Thêm Middleware Intlayer
Remix 3 cung cấp quy trình middleware có thể kết hợp thông qua
createRouter({ middleware: [...] }).remix-intlayercung cấp middlewareintlayer(). Đối với mỗi yêu cầu đến, nó phân giải ngôn ngữ bằng cách sử dụng:- URL, trong mọi chế độ định tuyến ngoại trừ
no-prefix: tiền tố đường dẫn (ví dụ/vihoặc/en) hoặc tham số tìm kiếm?locale=. - Ngôn ngữ được lưu bởi máy khách: cookie lưu trữ (
INTLAYER_LOCALE) hoặc tiêu đề tùy chỉnh (x-intlayer-locale). - Thương lượng
Accept-Languagetiêu chuẩn, dự phòng vềdefaultLocaleđã định cấu hình của bạn.
Kết quả được lưu trữ trong ngữ cảnh yêu cầu Remix dưới dạng
context.intlayer(hoặccontext.get(Intlayer)), cùng vớilocale,defaultLocalevàavailableLocales. Middleware sau đó chạy phần còn lại của yêu cầu bên trong phạm viAsyncLocalStorageđược liên kết với ngữ cảnh đó, cho phép các hook của gói đọc ngôn ngữ mà không cần đối số, trong các trình xử lý tuyến đường, chế độ xem cũng như các thành phầnremix/ui:typescriptSao chép mãSao chép mã vào clipboard
useIntlayer("home", "fr")hoặcuseIntlayer("faq", { item: 2 })ghi đè ngôn ngữ yêu cầu cho một lệnh gọi, vàuseDictionary(homeContent)đọc từ điển đã nhập thay vì một khóa. Bên ngoài một yêu cầu, các hook sẽ quay về ngôn ngữ mặc định.Middleware cũng chuẩn bị các từ điển Intlayer khi máy chủ khởi động, do đó việc thiếu
intlayer buildsẽ không để lại sổ đăng ký trống rỗng.Đặt
routing.enableProxy: falsetrongintlayer.config.tsđể chỉ giữ lại việc xác định locale và tự xử lý routing.intlayer({ ignore })giữ nguyên các request khớp (ví dụ một tiền tố API), vàintlayer({ isDevServer })kiểm soát việc locale đã lưu có điều khiển các chuyển hướng trong chế độ tự động mặc định củaenableProxyhay không.- URL, trong mọi chế độ định tuyến ngoại trừ
Xác định các tuyến an toàn kiểu
Xác định các tuyến ứng dụng của bạn bằng
route()từremix/routes:src/routes.tsSao chép mãSao chép mã vào clipboard
import { route } from "remix/routes"; export const routes = route({ // Tuyến đường mặc định của ngôn ngữ home: "/", // Tuyến đường được bản địa hóa với đoạn động :locale localizedHome: "/:locale", });Việc sử dụng
route()giúp bạn tạo URL an toàn về mặt kiểu dữ liệu trong toàn bộ ứng dụng của mình:typescriptSao chép mãSao chép mã vào clipboard
Kết xuất các trang được bản địa hóa bằng JSX
Remix 3 sử dụng
remix/uicho các thành phần JSX. Một thành phần là một hàm thiết lập (setup function) trả về một hàm kết xuất (render function). Props được truyền qua mộthandlecó định kiểu (ví dụ:handle.props.locale):Bắt đầu với một khung
Documentdùng chung thiết lập các thuộc tính<html lang="..." dir="...">từ ngôn ngữ được phân giải bởi middleware:src/views/document.tsxSao chép mãSao chép mã vào clipboard
import { getHTMLTextDir } from "intlayer"; import { useLocale } from "remix-intlayer"; import type { Handle, RemixNode } from "remix/ui"; type DocumentProps = { title: string; children?: RemixNode; }; export const Document = (handle: Handle<DocumentProps>) => () => { const { title, children } = handle.props; const { locale } = useLocale(); return ( <html lang={locale} dir={getHTMLTextDir(locale)}> <head> <meta charSet="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>{title}</title> </head> <body>{children}</body> </html> ); };Sau đó tạo trang chủ. Nó đọc từ điển bản địa hóa bằng
useIntlayervà hiển thị bộ chuyển đổi ngôn ngữ:src/views/home.tsxSao chép mãSao chép mã vào clipboard
import { getLocaleName, getLocalizedUrl, getPathWithoutLocale } from "intlayer"; import { useIntlayer, useLocale } from "remix-intlayer"; import { Document } from "./document"; export const HomePage = () => () => { const { locale, availableLocales } = useLocale(); const home = useIntlayer("home"); const pathWithoutLocale = getPathWithoutLocale(); return ( <Document title={home.title}> <header> <nav aria-label="Languages"> <span>{home.switchLanguage}</span> <ul> {availableLocales.map((localeItem) => { const isActive = localeItem === locale; return ( <li key={localeItem} class="p-1"> <a href={getLocalizedUrl(pathWithoutLocale, localeItem)} class={isActive ? "active" : undefined} aria-current={isActive ? "page" : undefined} > {getLocaleName(localeItem, locale)} </a> </li> ); })} </ul> </nav> </header> <main> <h1>{home.title}</h1> <p>{home.description}</p> </main> </Document> ); };Remix JSX không phải là React:
classđược viết nguyên trạng (classNamecũng được chấp nhận), và việc kết xuất lại được kích hoạt rõ ràng bằnghandle.update(). Các giá trị nội suy được thoát tự động. Các hook Intlayer là các hàm thông thường đọc phạm vi yêu cầu, vì vậy chúng có thể được gọi từ hàm setup hoặc hàm render.Kết nối router và máy chủ
Tạo
src/router.tsxđể đăng ký middleware và định nghĩa các hành động định tuyến. Sử dụngremix/middleware/renderđể cài đặt trình trợ giúpcontext.render(), và truyền trực tiếp thành phần JSX của bạn:src/router.tsxSao chép mãSao chép mã vào clipboard
import { isDeclaredLocale } from "intlayer"; import { intlayer } from "remix-intlayer"; import { render } from "remix/middleware/render"; import { createRouter } from "remix/router"; import { routes } from "./routes"; import { HomePage } from "./views/home"; // 1. Initialize router with Intlayer + render middleware export const router = createRouter({ middleware: [intlayer(), render()], }); // 2. Map route handlers router.map(routes, { actions: { // Default locale route home(context) { return context.render(<HomePage />); }, // Localized route localizedHome(context) { if (!isDeclaredLocale(context.params.locale)) { return new Response("Not Found", { status: 404 }); } return context.render(<HomePage />); }, }, });context.renderchấp nhận mộtResponseInittùy chọn làm đối số thứ hai, ví dụ:context.render(<NotFoundPage />, { status: 404 }). Ngôn ngữ đã phân giải vẫn có thể truy cập được từ trình xử lý dưới dạngcontext.intlayer.locale, chẳng hạn để tạo tải trọngResponse.json.Bây giờ hãy kết nối
src/server.tsbằng cách sử dụngremix/node-fetch-servercho Node.js (hoặc xuất trình xử lýfetchtrực tiếp cho Bun, Deno, hoặc Cloudflare Workers):src/server.tsSao chép mãSao chép mã vào clipboard
import * as http from "node:http"; import { createRequestListener } from "remix/node-fetch-server"; import { router } from "./router"; const PORT = Number(process.env.PORT || 3000); // Máy chủ HTTP Node.js const server = http.createServer( createRequestListener((request) => router.fetch(request)) ); server.listen(PORT, () => { console.log(`Máy chủ đang chạy tại http://localhost:${PORT}`); }); // Xuất cho Bun / Deno / Cloudflare Workers export default { port: PORT, fetch(request: Request) { return router.fetch(request); }, };Kiểm tra và tự động điền bản dịch
Intlayer cung cấp một CLI để kiểm tra các bản dịch còn thiếu và tự động điền chúng bằng AI:
bashSao chép mãSao chép mã vào clipboard
Cấu hình TypeScript
Cấu hình tsconfig.json để trỏ JSX đến runtime remix/ui và bao gồm các kiểu .intlayer đã tạo:
Sao chép mã vào clipboard
jsxImportSource: "remix/ui"là yếu tố giúp<HomePage />phân giải thành hàmcreateElementcủa Remix thay vì của React. Không có runtime React nào được tải.
Kết luận
Với Remix 3 và Intlayer, bạn sở hữu một ngăn xếp công nghệ tinh gọn, được định kiểu hoàn chỉnh và có khả năng di chuyển linh hoạt trên nhiều môi trường chạy tuân thủ các tiêu chuẩn web mở. Ứng dụng của bạn có thể mở rộng dễ dàng từ các trang tiếp thị bản địa hóa đơn giản đến các dịch vụ kết xuất tại vùng biên (edge) phân tán trên toàn cầu.
