Mengapa teks terjemahan jadi kotak
Anda sudah menerjemahkan gamenya, ekspornya berjalan bersih, dan kotak dialognya penuh □□□. Itu hampir tak pernah masalah terjemahan — itu masalah font, dan perbaikannya berbeda dari dua kegagalan yang sering dikira sama. Berikut cara membedakan glif yang hilang dari karakter yang dibuang dan dari mojibake, serta bagaimana masing-masing diperbaiki di Unity, TextMeshPro, Ren'Py, dan alat runtime.
Ekspor selesai, game diluncurkan, dan tiap baris dialog adalah deretan persegi kosong yang identik. Tak ada yang salah dengan terjemahannya. Teks di dalam berkas persis seperti yang dikembalikan penyedia, dan kalau Anda membuka berkas itu di editor teks, ia terbaca benar. Yang gagal adalah langkah terakhir rantainya: font yang diserahkan game ke perender tidak punya gambar untuk karakter-karakter itu.
Apa sebenarnya kotak tofu itu
Font adalah tabel pencarian dari titik kode Unicode ke sebuah bentuk. Ketika perender diminta menggambar titik kode yang tak dimiliki font itu, ia menggantinya dengan glif hilang milik font tersebut — biasanya persegi kosong atau bersilang, resminya disebut .notdef dan dikenal di mana-mana sebagai kotak tofu. Satu kotak sama dengan satu karakter yang tak bisa digambar font. Itu seluruh mekanismenya.
Dua konsekuensi mengikutinya, dan keduanya berguna untuk diagnosis. Pertama, jumlah kotak cocok dengan jumlah karakter: lima karakter Thai menghasilkan lima kotak, bukan deretan kacau yang lebih pendek. Kedua, string-nya utuh di memori — game masih bisa mengukurnya, membandingkannya, menyimpannya, dan memuatnya kembali. Hanya pikselnya yang hilang. Inilah sebabnya sebuah menu terjemahan bisa sepenuhnya tak terbaca dan tetap bisa dinavigasi dengan benar.
Tiga gejala, tiga masalah berbeda
Sebagian besar kebingungan seputar "terjemahan saya rusak" adalah orang menerapkan perbaikan salah satu dari ketiganya ke yang lain. Baca bentuk kerusakannya sebelum mengubah apa pun.
- Kotak □□□ — karakternya benar, font-nya tak bisa menggambarnya. Perbaiki font-nya.
- ???? — karakternya hilang. Sesuatu meng-encode ulang string itu ke himpunan karakter yang lebih sempit dan mengganti semua yang tak bisa diwakilinya. Tak ada font yang bisa mengembalikannya. Perbaiki encoding-nya, atau pilih bahasa target yang muat di formatnya.
- Latin kacau seperti
テã‚ストatauテキストyang tampil sebagaiテキスト— mojibake. Byte-nya benar, dekodernya yang salah: teks yang ditulis dalam satu encoding dibaca sebagai encoding lain. Perbaiki encoding mana yang dibaca.
Pemisah cepat: kotak dan mojibake sama-sama meninggalkan jumlah byte yang kira-kira sebanding dengan aslinya, tetapi mojibake menghasilkan karakter sampah yang terlihat dan beragam sementara tofu menghasilkan persegi yang identik dan seragam. Seragam berarti "font". Beragam berarti "encoding".
Kotak: glif yang hilang
Game dikirim dengan font yang hanya mencakup apa yang ia butuhkan. Tak ada yang rusak di pipeline-nya — Anda meminta titik kode yang tak pernah disertakan sang artis. Perbaikannya selalu memberi perender sebuah font yang punya glif itu, entah dengan mengganti font-nya atau dengan menambahkan fallback yang dikonsultasikan perender ketika font utama kosong.
Tanda tanya: karakternya dibuang
Ketika sebuah string harus ditulis kembali ke format yang menyimpan teks dalam encoding lawas satu atau dua byte, tiap karakter di luar encoding itu harus menjadi sesuatu. Secara konvensi, sesuatu itu adalah ?. Shift-JIS dan cp932 bisa menampung Jepang, ASCII, dan sangat sedikit selain itu; kolom ASCII ketat tak bisa menampung Yunani, Kiril, Thai, maupun CJK. Ini sifat format berkasnya, bukan font-nya, dan terjadi saat ekspor — begitu game membaca berkasnya, informasinya sudah hilang.
RuneTranslate punya satu engine tempat ini menjadi batas nyata dan itu dinyatakan alih-alih disembunyikan: YU-RIS meng-encode ulang string-nya sebagai cp932, yang ramah untuk keluaran Inggris dan Latin lainnya tetapi mengirim Thai sebagai ?. Target non-cp932 pada engine itu butuh font hack yang belum dibangun.
Latin kacau: mojibake
Teks Jepang yang ditulis sebagai Shift-JIS lalu dibaca sebagai UTF-8 (atau sebaliknya) menghasilkan deretan panjang huruf Latin beraksen dan karakter penggambar kotak. Ini muncul ketika sebuah alat menulis berkas dalam encoding yang salah, atau ketika loader milik game mengasumsikan encoding yang tidak dipakai ekspor Anda. Perbaikannya adalah menulis berkas dalam encoding yang diharapkan engine — bukan menukar font-nya, yang tak akan mengubah apa pun.
Kenapa CJK dan Thai paling terpukul
Latin butuh sekitar seratus glif. Jepang butuh beberapa ribu, Mandarin lebih banyak lagi. Berkas font itu besar, dan game mengirim yang terkecil yang mencakup aksaranya sendiri, jadi cakupan yang Anda warisi bergantung sepenuhnya pada bahasa apa game itu dibangun.
- Game yang dibangun untuk bahasa Jepang biasanya membawa kana, kanji umum, dan ASCII. Terjemahkan ke Rusia, Yunani, Thai, atau Korea dan tiap karakter non-ASCII rontok.
- Game yang dibangun untuk bahasa Inggris biasanya hanya membawa Latin — jadi Jepang, Mandarin, Korea, Thai, Yunani, dan Kiril gagal sekaligus.
- Thai adalah kasus terburuk dalam praktik: ia berada di luar tiap font game umum, dan ia juga butuh tanda vokal serta nada gabungan yang diposisikan di atas dan di bawah karakter dasar, jadi font yang secara teknis punya titik kodenya pun masih bisa merendernya buruk.
- Latin tidak otomatis aman. Polandia, Ceko, Hungaria, Turki, Vietnam, dan Rumania memakai karakter Latin-Extended yang sering dihilangkan oleh font yang dibangun untuk Inggris atau Jepang. RuneTranslate menyertakan font yang lebih luas persis untuk target itu pada Ren'Py karena "Latin aman-aman saja" ternyata keliru.
Unity dan TextMeshPro secara khusus
Unity punya dua sistem teks dan keduanya gagal dengan cara berbeda. Text uGUI lawas memakai objek Font. TextMeshPro — yang dipakai sebagian besar game modern — sama sekali tidak memakai berkas font saat runtime. Ia memakai aset font TMP: atlas tekstur berisi gambar glif yang sudah dirender lebih dulu, plus tabel yang memetakan titik kode ke posisi di atlas itu.
Itu sebabnya aset font TMP punya himpunan karakter tetap. Ketika pengembang membangkitkannya, mereka memilih satu rentang karakter — biasanya hanya bahasa yang mereka kirim — dan TMP memanggang persis glif itu ke atlas. Aset font static tak akan pernah bisa merender apa pun di luar himpunan itu, apa pun yang Anda berikan. Aset font dynamic menyimpan rujukan ke berkas font sumber dan bisa meraster glif baru sesuai permintaan, dan itulah satu-satunya mode yang bisa tumbuh mencakup bahasa yang tak pernah dipertimbangkan pengembang.
Pintu darurat TMP adalah daftar fallback. Tiap aset font punya daftar m_fallbackFontAssets, dan TMP Settings punya daftar fallback global; ketika aset utama tak punya glif untuk sebuah titik kode, TMP menelusuri daftar itu mencari yang punya. Ini tempat yang benar untuk campur tangan, karena ia membiarkan font milik game tetap memegang semua yang sudah bisa digambarnya — UI mempertahankan tampilan yang dimaksudkan dan hanya karakter yang tak bisa ia tangani yang datang dari tempat lain.
Memperbaikinya dengan alat runtime
XUnity.AutoTranslator meng-hook game saat berjalan dan bisa menukar font dari berkas konfigurasinya. Pengaturan yang relevan, di bawah [Behaviour]:
OverrideFont— mengganti font yang dipakai komponenTextUI Unity lawas. Menerima nama font yang bisa diselesaikan oleh game atau OS.OverrideFontTextMeshPro— mengganti aset font TMP sepenuhnya. Arahkan ke berkas AssetBundle font TMP, atau ke nama aset yang sudah dimiliki game.FallbackFontTextMeshPro— yang lebih aman dari keduanya: menambahkan font yang dikonsultasikan TMP hanya untuk glif yang tak dimiliki aset milik game, dan membiarkan huruf aslinya di tempat lain.- tmp_font_assetbundles — koleksi AssetBundle font TMP siap pakai yang dirawat komunitas, yang biasanya menjadi tujuan
OverrideFontTextMeshProdanFallbackFontTextMeshPro. Ini dibangun per versi Unity, dan bundle yang dibangun untuk versi Unity berbeda dari gamenya akan gagal dimuat — mencocokkan versinya adalah langkah yang sering terlewat.
Alat runtime bersifat per-mesin dan per-konfigurasi: ia memperbaiki game di PC tempat ia dipasang, dan siapa pun yang menjalankan build itu butuh penyiapan yang sama. RuneTranslate bisa membaca dan menulis berkas _AutoGeneratedTranslations.txt milik plugin itu, jadi proyek yang sudah memakainya bukan jalan buntu — lihat perbandingannya untuk tahu di mana tiap pendekatan cocok.
Memperbaikinya di level berkas
RuneTranslate menempuh jalur fallback langsung di dalam data game. Saat ekspor Unity, ia menemukan TMP Settings milik game, sebuah aset font yang bisa dipakai sebagai templat, dan sebuah font, lalu membangun aset font TMP baru dalam mode Dynamic di sekitar font bawaan yang mencakup aksara target, dan menambahkannya ke daftar fallback. Entri fallback yang sudah ada dibiarkan tak tersentuh, dan font milik game tetap utama — jadi game Jepang yang diterjemahkan ke Thai mempertahankan gaya aslinya untuk semua yang Latin dan menarik glif Thai dari aset yang disuntikkan.
Dua catatan jujur soal itu. Ia butuh TMP Settings, templat aset font yang bisa dipakai, dan sebuah Font berada di kontainer aset game yang sama; game yang menata ketiganya berbeda bisa berada di luar jangkauannya. Dan ketika penyuntikan dilewati, ekspornya mengatakan begitu di peringatannya alih-alih selesai hijau — ekspor yang dikirim sebagai kotak tak boleh tampak identik dengan yang berhasil. Kalau Anda melihat peringatan itu, jalur alat runtime di atas adalah rencana cadangannya.
Ren'Py mencapai hasil yang sama lewat mekanisme berbeda, karena Ren'Py tak punya TMP: RuneTranslate bisa menyertakan font CJK atau non-Latin ke dalam build hasil ekspor dan mendaftarkannya lewat config.font_replacement_map milik Ren'Py sendiri, sehingga engine menggantinya di mana pun font game akan kurang.
Daftar periksa kerja
- Lihat kerusakannya. Persegi seragam, karakter
?, atau huruf kacau — putuskan yang mana dari ketiganya sebelum menyentuh apa pun. - Kalau
?, buka berkas hasil ekspor. Kalau tanda tanyanya ada di dalam berkas, karakternya hilang saat penulisan dan tak ada font yang menolong; periksa apakah encoding string engine itu bisa menampung bahasa target Anda. - Kalau huruf kacau, periksa encoding yang diharapkan engine untuk berkas itu, bukan font-nya.
- Kalau kotak, pastikan isi berkasnya benar — hampir selalu begitu — lalu perlakukan sebagai pekerjaan font.
- Pada Unity, lebih baik menambahkan fallback ketimbang mengganti font game. Penggantian mengubah tampilan tiap string, termasuk yang tadinya terender baik.
- Kalau Anda memakai AssetBundle font TMP, cocokkan dengan versi Unity gamenya.
- Ekspor ulang lalu periksa karakter spesifik yang tadinya gagal, bukan hanya baris dialog pertama. Latin-Extended dan tanda Thai sering lolos pemeriksaan sekilas lalu gagal di tempat lain.
Ke mana selanjutnya
Untuk alur kerja Unity lengkap — teks apa yang benar-benar diekspos Unity, dan apa yang tetap di luar jangkauan — baca cara menerjemahkan game Unity dan halaman engine Unity. Teks yang dipanggang ke dalam artwork alih-alih data adalah masalah terpisah dengan alat terpisah: lihat terjemahan gambar. Dan FAQ mencakup sisa kejutan awal yang umum.
RuneTranslate gratis dipakai dengan tiap engine dan tiap penyedia terbuka, termasuk tiga yang sama sekali tak butuh kunci API. Ia mengurai berkas milik game sendiri dan mengekspor build terjemahan yang bisa dimainkan dan Anda simpan. Unduh sekarang atau jelajahi engine yang didukung.
Siap mencoba RuneTranslate?
Tier gratis membuka setiap engine + setiap penyedia terjemahan. Supporter ($3/mo) membuka kecepatan penuh.
Unduh untuk Windows
