unreal · guides · engine · localization
Cách dịch game Unreal Engine
Game Unreal để văn bản trong các bảng .locres đã biên dịch, nằm trong container .pak hoặc IoStore. Cách đọc chúng, và vì sao kết quả là một pak ghi đè nhỏ chứ không phải game dựng lại.
Game Unreal Engine trông như thứ khó dịch nhất trên ổ đĩa của bạn. Không có thư mục data, không có file kịch bản, không có .json nào để mở, chỉ có một file thực thi, một thư mục Content/Paks chứa một hai file .pak khổng lồ, và có thể thêm một cặp container .utoc/.ucas. Tin tốt là văn bản bạn cần thường không bị cố tình giấu trong các file đó. Unreal có hệ thống bản địa hóa chính thức, và hầu hết game phát hành đều dùng nó. Việc của bạn là tìm bảng đó, thay các chuỗi, rồi đưa cho engine một file nhỏ có độ ưu tiên cao hơn bản gốc.
Chính phần cuối này khiến Unreal dễ chịu khi bạn đã hiểu nó. Bạn không dựng lại một game 60 GB. Bạn tạo một kho ghi đè đo bằng kilobyte và thả cạnh các file gốc.
Một điều trước khi vào các bước: hỗ trợ Unreal trong RuneTranslate đã được xác nhận chơi được trên các tựa UE4 và UE5 thật, nhưng phạm vi định dạng rất lớn và mỗi studio đóng gói một kiểu. Hãy kiểm tra bản dựng đã xuất trong game trước khi cam kết một lượt dịch dài.
Một game Unreal thực sự phát hành những gì
Unreal giữ văn bản người chơi nhìn thấy trong các file `.locres`, dạng đã biên dịch của FTextLocalizationResource. Mỗi văn hóa (culture) có một file, đặt theo đường dẫn như <Game>/Content/Localization/Game/ja/Game.locres, cùng các file anh em cho en, zh-Hans và bất cứ ngôn ngữ nào studio phát hành. Một game không có bản dịch nào vẫn thường có một file, cho văn hóa mà nó được viết ban đầu.
.locres không phải file văn bản và không phải danh sách khóa/giá trị đơn giản. Nó là một bảng nhị phân tổ chức theo namespace, mỗi namespace chứa các khóa, mỗi khóa trỏ tới một chuỗi. Ở các phiên bản hiện đại, namespace và khóa được lưu dưới dạng hash (CRC32 ở phiên bản 2, CityHash64 trên UTF-16 ở phiên bản 3) thay vì tên đọc được, còn bản thân các chuỗi nằm trong một bảng tra cứu dùng chung, đã khử trùng lặp, có đếm tham chiếu. Lúc chạy, engine không bao giờ tra một chuỗi theo văn bản tiếng Anh của nó, mà tra theo cặp namespace/khóa, vốn được biên dịch vào Blueprint và C++ của game khi build.
Cấu trúc đó quyết định cách chỉnh sửa an toàn duy nhất. RuneTranslate giữ nguyên từng byte mọi hash namespace, hash khóa và hash chuỗi gốc, chỉ đổi phần giá trị, rồi dựng lại bảng chuỗi đã khử trùng lặp cùng số đếm tham chiếu của nó. Không có gì tính lại hash, nên không thể sinh ra khóa mà game không tìm thấy. Bản dịch được phép dài hơn hay ngắn hơn bản gốc.
Các file .locres này sau đó được đóng vào kho .pak, nhận diện bằng giá trị ma thuật 0x5A6F12E1 trong phần chân ở cuối file, hoặc với các tựa UE5 hiện đại thì vào container IoStore .utoc/.ucas.
Kiểm tra phạm vi trước khi bỏ ra một giờ
.locres bao gồm giao diện, menu, thông báo hệ thống, văn bản hướng dẫn, tên vật phẩm và kỹ năng, và phụ đề, tức khoảng 90% văn bản nhìn thấy trong một game điển hình. Đó là phần RuneTranslate đọc trước tiên.
Những gì .locres không bao gồm: văn bản được biên dịch vào DataTable hoặc nướng vào các gói `.uasset` đã cook. Một số studio, nhất là ở dự án nhỏ hơn hoặc dựa nhiều vào Blueprint, để hội thoại ở đó thay vì trong hệ thống bản địa hóa. RuneTranslate đọc cả phần này. Khi game không có .locres riêng, nó giải nén các file của game và quét các gói đã cook để lấy văn bản, việc này mất vài phút thay vì vài giây với game lớn, và với game có các kho .pak rời, nó còn thêm phần hội thoại nằm trực tiếp trong gói mà .locres bỏ sót. Một khoảng trống duy nhất: game UE5 IoStore có .locres riêng thì chỉ lấy văn bản .locres.
Đáng biết sớm: cách nhanh nhất để kiểm tra là chạy bước tạo dự án và xem cái gì ra. Vài trăm chuỗi ngắn đều giống Continue, Options, Are you sure? nghĩa là giao diện đã được bản địa hóa còn kịch bản thì chưa. Vài nghìn chuỗi gồm cả câu đầy đủ nghĩa là bạn đang ở thế tốt.
UE5 IoStore thì khác, và việc trích xuất nhắm đúng mục tiêu
Các tựa UE5 ngày càng phát hành container IoStore thay cho pak thường: một thư mục .utoc đi cùng một khối dữ liệu .ucas, dùng nén Oodle. Cách làm ngây thơ ở đây là giải nén toàn bộ, mà với một game 105 GB thì không còn là một cách làm nữa.
RuneTranslate kèm sẵn retoc (giấy phép MIT) và yêu cầu nó chuyển các container thành pak kiểu cũ chỉ lọc lấy các file bản địa hóa, tương đương to-legacy -f locres --no-shaders --no-script-objects. Một tựa IoStore 105 GB được lọc xuống còn vài kilobyte .locres, trong vài giây thay vì hàng giờ. retoc cũng xử lý nén Oodle của container, đó là lý do game IoStore tránh được vấn đề Oodle mà pak rời có thể gặp.
Điểm quan trọng là IoStore chỉ làm phức tạp việc đọc. Việc ghi thì chung cho mọi loại, và đó là phần tiếp theo.
Đầu ra là pak ghi đè, không phải game dựng lại
Đây là phần không hướng dẫn cạnh tranh nào giải thích tử tế, và là lý do dịch Unreal rẻ một khi nó đã chạy được.
Unreal mount các file pak theo một thứ tự xác định, và mọi kho có tên kết thúc bằng `_P` được mount sau cùng. Mount sau thì thắng. Vì vậy một kho nhỏ chỉ chứa .locres đã sửa của bạn, đặt ở cùng đường dẫn ảo mà game gốc dùng, đơn giản là che khuất bản gốc: trình quản lý bản địa hóa nạp file của bạn và không bao giờ thấy file đã phát hành.
- Không cần ký lại. Bản ghi đè không đụng tới các kho gốc của game, nên không có gì để ký lại.
- Một file thường, không nén. Bản ghi đè được ghi thành pak thường không nén mà engine đọc trực tiếp.
- Không đóng gói lại game. Các kho gốc không bị đụng. Bản cài 60 GB vẫn là 60 GB; bản dịch của bạn là một file đo bằng kilobyte.
- Dùng được cả với game IoStore.
.locresđược đọc qua hệ thống file pak chứ không qua trình nạp gói Zen, nên một_P.pakrời thông thường vẫn được nhận, kể cả với game UE5 có mọi asset nằm trong.utoc/.ucas.
Bạn cài nó bằng cách chép _P.pak được tạo ra vào <Game>/Content/Paks/, cùng thư mục chứa các file gốc. Một số game còn mount cả thư mục con ~mods/, cách này cũng hiệu quả tương đương. Gỡ bản dịch chỉ là xóa đúng một file đó, nên quay lui rất dễ và thử sớm rất an toàn.
Các bước
- Cài RuneTranslate từ trang tải xuống và đăng nhập. Lần mở đầu tiên cần đăng nhập miễn phí (Patreon, Google hoặc email); gói Miễn phí mở khóa mọi engine và mọi nhà cung cấp trừ RuneLingua, chỉ giới hạn tốc độ xử lý và cho giữ một dự án mỗi lần.
- Tạo dự án mới và trỏ nó vào thư mục gốc của game, thư mục chứa file thực thi và thư mục
<Game>. Việc phát hiện tìmContent/Paksvà dấu ma thuật ở chân pak, hoặc tìm.utoc/.ucas. - Để RuneTranslate mở các kho nén. Hầu hết game không cần bạn làm gì ở bước này.
- Chờ trích xuất xong. Bạn nhận được các mục
.locrescủa văn hóa nguồn, nhóm theo mục tiêu bản địa hóa, sẵn sàng để xem lại. - Chọn nhà cung cấp và dịch. Chuỗi giao diện ngắn và hội thoại dài có thể được định tuyến tới các nhà cung cấp khác nhau nếu bạn chỉ muốn tốn tiền ở nơi thật cần.
- Xem lại kết quả. Chuỗi menu là chỗ dịch máy yếu nhất: một chữ
SavehayLoadtrần trụi không có ngữ cảnh, và một nút hai chữ trả về thành cả câu sẽ tràn khỏi widget của nó. - Xuất. RuneTranslate ghi một
_P.pakchứa văn bản đã dịch của bạn ở đúng đường dẫn tương đối theo engine, kèm một README. Với vài game mà engine không bao giờ nạp pak bản vá, nó còn ghi văn bản thành.locresrời, và README cho biết đặt nó ở đâu. - Chép file đó vào
<Game>/Content/Paks/và mở game.
Hãy thử sau bước 8 với một ít chuỗi đã dịch trước khi cho cả game chạy qua nhà cung cấp. Nếu bản ghi đè sắp bị bỏ qua, do sai thư mục, sai văn hóa hoặc cách mount bất thường, bạn muốn biết trong năm phút chứ không phải sau khi đã trả tiền cho 9,000 chuỗi.
Chỗ giữ chỗ và rich text
Định dạng FText của Unreal dùng {0}, {1} cho đối số theo vị trí và {PlayerName}, {Count} cho đối số đặt tên, cộng thêm mã đánh dấu <RichText> với dấu đóng </> để tạo kiểu trong dòng. Nếu một nhà cung cấp dịch làm rơi hay làm méo một trong số đó, game không hiển thị một câu sai nhẹ, mà hiển thị chuỗi định dạng hỏng, hoặc đối số lặng lẽ biến mất khỏi dòng.
RuneTranslate che từng cái thành chỗ giữ chỗ trung tính trước khi nhà cung cấp nhìn thấy chuỗi, rồi khôi phục sau đó. Nhà cung cấp dịch xung quanh các dấu chứ không đi xuyên qua chúng, nên một mô hình cho rằng dấu ngoặc nhọn trông như lỗi đánh máy cũng không xóa được đối số. Nếu muốn đi xa hơn và giữ một số chuỗi nhất định hoàn toàn không dịch, bộ lọc loại trừ bằng regex dùng được trên mọi engine, còn bảng thuật ngữ giữ danh từ riêng ổn định trên cả game.
Cái bẫy dấu, vốn là lỗi mã hóa chứ không phải phông chữ
Điều này đáng ghi riêng vì triệu chứng chỉ sai hướng hoàn toàn. Unreal tuần tự hóa một chuỗi với tiền tố độ dài: độ dài dương nghĩa là một byte mỗi ký tự, độ dài âm nghĩa là UTF-16. Engine chỉ chọn dạng hẹp khi mọi ký tự đều là ASCII 7-bit, phép kiểm tra của nó loại bất cứ thứ gì trên 0x7F. Trình nạp của nó được xây theo cùng cách, nên nếu nhận một chuỗi hẹp có byte cao, nó thay mỗi byte bằng một dấu ? nguyên văn.
Hệ quả thực tế: một bản dịch chứa poción mágica ghi ở dạng hẹp sẽ đến tay người chơi thành poci?n m?gica. Và dải bị ảnh hưởng là U+0080-U+00FF, chính xác là các chữ có dấu của tiếng Tây Ban Nha, Pháp, Đức, Bồ Đào Nha, Ý và các ngôn ngữ Bắc Âu. Tiếng Ba Lan, Thổ Nhĩ Kỳ, Séc, Hy Lạp, Cyrillic, tiếng Nhật và tiếng Trung đều nằm trên U+00FF, tự động đi nhánh rộng và không bao giờ bị ảnh hưởng.
Vậy dấu hiệu nhận biết là: dấu bị hỏng ở tiếng Tây Ban Nha nhưng tiếng Nga vẫn ổn. Nếu bạn thấy vậy, đó là lỗi mã hóa của thứ đã ghi file, không phải thiếu glyph trong phông chữ của game, vì glyph thiếu hiện thành ô vuông hoặc không hiện gì, không bao giờ thành dấu hỏi. RuneTranslate từng có đúng lỗi này và đã sửa ở 0.49.4; bộ mã hóa giờ nằm ở một chỗ và ghi dạng rộng cho mọi thứ ngoài ASCII. Đáng biết vì các công cụ khác trong mảng này vẫn làm sai.
Chọn nhà cung cấp
Bốn trong mười một nhà cung cấp hoàn toàn không cần khóa API (Google, DeepL miễn phí, các mô hình Classic/Next-gen của DeepL và Gemini Nano chạy ngay trên PC của bạn qua Chrome), và gói Miễn phí cho bạn dùng cả bốn. Với game phần lớn là giao diện, một nhà cung cấp miễn phí thực sự ổn. Với các tựa nặng hội thoại, nhà cung cấp LLM xử lý ngữ cảnh tốt hơn nhiều; OpenAI, Anthropic, DeepSeek, bất kỳ endpoint tương thích OpenAI nào, và mô hình cục bộ qua Ollama hoặc LM Studio đều dùng được, và các gói trả phí còn kèm RuneLingua, dịch AI do chúng tôi làm, không cần cài đặt gì. Bài so sánh nhà cung cấp đi qua điểm mạnh và yếu của từng nhà, kèm số liệu chi phí thật.
Xử lý sự cố
Game chạy nhưng không có gì được dịch
Hầu như luôn là một trong ba nguyên nhân. File không nằm trong <Game>/Content/Paks/: đặt cạnh file thực thi thì không có tác dụng. Tên file mất hậu tố _P, khi đó nó được mount theo thứ tự bảng chữ cái thông thường và pak gốc có thể thắng. Hoặc game đang chạy ở một văn hóa bạn chưa dịch: nó nạp .locres của văn hóa mà nó xác định lúc khởi động, nên game ép dùng en sẽ bỏ qua bản ghi đè chỉ viết cho ja. Hãy kiểm tra cài đặt ngôn ngữ của game trước.
Trích xuất thất bại với pak rời nén bằng Oodle
Một file .pak rời nén bằng Oodle cần trình giải nén không thể kèm sẵn. Nếu game cũng phát hành container IoStore, đường retoc xử lý được Oodle và bạn ổn. Nếu chỉ có pak rời thì hiện đây là điểm dừng cứng, được báo rõ ràng chứ không phải kết quả rỗng im lặng.
Game không có .locres ở bất kỳ đâu
Khi đó văn bản của nó được biên dịch vào các asset đã cook, và RuneTranslate đọc nó từ đó: nó giải nén các file của game và quét các gói đã cook để lấy văn bản, việc này có thể mất vài phút với game lớn. Nếu vẫn không tìm thấy gì, RuneTranslate nói rõ điều đó thay vì đưa bạn một dự án rỗng.
Việc phát hiện hoàn toàn không chạy
Hãy trỏ vào thư mục chứa file thực thi, không phải chính Content/Paks và không phải thư mục cha đầy các game khác. Nếu vẫn không phát hiện được, cách đóng gói thuộc dạng bất thường và đáng báo lại: định dạng pak có bố cục chân theo từng phiên bản, và một biến thể chưa ai thấy chính là loại thứ sẽ được bổ sung.
Những giới hạn thẳng thắn
Hỗ trợ Unreal đã được xác nhận chơi được trong game trên các tựa UE4 và UE5, qua .locres trong kho .pak và UE5 IoStore, và qua văn bản đọc từ asset đã cook. Game UE5 IoStore có .locres riêng thì chỉ lấy văn bản đó, không lấy phần hội thoại trong asset đã cook bên cạnh. Pak rời nén Oodle mà không có IoStore đi kèm không được hỗ trợ. Pak bắt buộc chữ ký không thể bị ghi đè, dù trên thực tế hiếm gặp. Và vì định dạng khác nhau rất nhiều giữa các phiên bản engine và studio, hãy coi lần xuất đầu tiên là một bài thử chứ không phải sản phẩm cuối.
Thứ bạn có được là một bản dựng đã dịch, chơi được, giữ trên máy của bạn: game gốc không bị chỉnh sửa, cộng một file nhỏ mà bạn có thể xóa để hoàn tác mọi thứ. Nếu bạn đang so sánh engine hoặc kiểm tra xem game của mình có được hỗ trợ không, trang engine Unreal có chi tiết kỹ thuật và mọi engine liệt kê mười tám định dạng được hỗ trợ, gồm cả Unity và RPG Maker. Nếu bạn mới làm quen toàn bộ quy trình, hãy bắt đầu với hướng dẫn chung rồi quay lại đây cho những phần riêng của Unreal.
Bài liên quan
Sẵn sàng thử RuneTranslate?
Gói miễn phí mở khóa mọi engine và mọi nhà cung cấp dịch trừ RuneLingua. Supporter ($3.99/tháng) mở khóa tốc độ tối đa.
Tải cho Windows & Linux
