While building a game in Ren'Py, you might notice something.
play music "戦闘BGM.ogg"
A Japanese filename. No errors. It just works.
You might think "Great, I'll use native-language filenames for easier management." But the short answer is: don't. This guide explains why it works, why it's risky, and what to do instead.
The Short Answer: It Works, But It's Unofficial
In Ren'Py 8.5.2, using non-ASCII characters (Japanese, Chinese, Korean, accented Latin, etc.) in image, audio, and video filenames works on most systems.
However, this is not an officially supported feature. Tom Rothamel (PyTom), Ren'Py's creator, has consistently stated on the Lemma Soft Forums:
Use ASCII in all filesystem object names. This makes distribution and cross-platform compatibility significantly easier.
The official documentation contains no statement that Unicode filenames are supported.
Why It Works: Python 3 Unicode Handling
Understanding why non-ASCII filenames work requires a quick history lesson about Python.
The Python 2 Era (Ren'Py 6.x / 7.x)
In Python 2, strings were byte sequences (str = bytes) by default. To handle non-ASCII text, you needed the u"" prefix to explicitly create a Unicode string.
# Python 2 — this is a byte string
"battle_bgm.ogg"
# Python 2 — this is a Unicode string
u"戦闘BGM.ogg"
In Ren'Py 6.x, audio file handling passed filenames to C functions as char*, causing UnicodeEncodeError crashes with non-ASCII names. This was fixed in 2014, but Python 2's string handling remained fundamentally limited.
The Python 3 Era (Ren'Py 8.x)
In Python 3, strings are Unicode by default.
# Python 3 — this is already Unicode
"戦闘BGM.ogg"
The u"" prefix is no longer needed. Every string literal is natively Unicode. Ren'Py 8.x runs on Python 3.12, so the encoding issues from the Python 2 era simply don't occur at the string level.
In other words, Ren'Py didn't add non-ASCII filename support — Python 3 made Unicode the default, and filenames started working as a consequence.
Why It's Risky: Three Ways Distribution Breaks
Working on your dev machine and working on a player's machine are two different things. Non-ASCII filenames hit three landmines during distribution.
Case 1: macOS Unicode Normalization
macOS's legacy filesystem HFS+ stores filenames in NFD (decomposed form). Windows and Linux typically use NFC (composed form).
For example, the Japanese character "が" has two internal representations:
| Form | Representation | Description |
|---|---|---|
| NFC | が (1 character) | Composed. Standard on Windows/Linux |
| NFD | か + ゙ (2 characters) | Decomposed. Standard on macOS HFS+ |
A file stored as NFC 戦闘BGM.ogg in a ZIP gets extracted as NFD 戦闘BGM.ogg on macOS. When Ren'Py searches for the NFC version, the file isn't found.
This exact problem was reported in the commercial Ren'Py game "WORLD END ECONOMiCA," where a Japanese filename 飛び_右下.png failed to load on macOS.
Case 2: ZIP Filename Encoding Mismatch
Ren'Py's build system produces ZIP and tar.bz2 distribution files. The ZIP format has no standardized filename encoding.
Python 3's zipfile module sets the UTF-8 flag (bit 11) when writing, but older extraction tools and some Windows Explorer versions ignore this flag. The result: garbled filenames and a game that won't start.
Case 3: Web and Android Builds Are Untested
Ren'Py supports web browser builds (Emscripten/WebAssembly) and Android APK builds. However, there is no official confirmation that non-ASCII filenames work correctly on these platforms. Web builds have additional concerns around HTTP URL encoding interactions.
The Safe Alternative: ASCII Filenames + Aliases
Keep filenames in ASCII and use define aliases for readability in your scripts.
Audio Files
# Files in audio/ use ASCII names
# audio/battle_bgm.ogg
# audio/village_theme.ogg
# audio/rain_ambient.ogg
define audio.battle_bgm = "audio/battle_bgm.ogg"
define audio.village_theme = "audio/village_theme.ogg"
define audio.rain_ambient = "audio/rain_ambient.ogg"
label start:
play music battle_bgm
play sound rain_ambient
Creating aliases in the audio namespace with define means you never need to write file paths in play music statements. The variable name tells you what the audio is, so readability isn't a problem.
Image Files
Ren'Py's automatic image detection maps space-separated filenames to image names (see the image display docs).
images/
├── bg forest.png → scene bg forest
├── bg castle.png → scene bg castle
├── eileen happy.png → show eileen happy
└── eileen sad.png → show eileen sad
For manual definitions, stick to ASCII as well.
image bg forest = "images/bg_forest.png"
image bg castle = "images/bg_castle.png"
Naming Conventions
Establishing project-wide rules keeps things manageable as your file count grows.
# Audio
audio/{type}_{description}.ogg
audio/bgm_battle.ogg
audio/sfx_sword_slash.ogg
audio/amb_rain.ogg
# Backgrounds
images/bg {location}.png
images/bg forest.png
images/bg castle.png
# Characters
images/{name} {expression}.png
images/eileen happy.png
images/eileen angry.png
Wrapping Up
- Does it work? — Non-ASCII filenames work in Ren'Py 8.5.2 on most systems
- Why? — Python 3's native Unicode string handling. Not an official Ren'Py feature
- Risks — macOS NFD normalization, ZIP encoding mismatches, untested Web/Android builds. Distribution can break silently
- Recommendation — ASCII filenames +
definealiases are safe and practical
For Ren'Py basics, see the getting started guide. For save-safe stat system design, see the stat management guide.
Official resources:
- Ren'Py Documentation — full reference for all features
- Displaying Images — image auto-detection and naming
- Audio — audio playback reference
- r/RenPy — community for questions and discussion