How to Display and Input Non-Latin Characters (Chinese, Japanese, Cyrillic) in Dear ImGui

To display and input non-Latin characters in Dear ImGui, load a Unicode-compatible font using ImFontAtlas::AddFontFromFileTTF with the appropriate glyph range helper (GetGlyphRangesCyrillic, GetGlyphRangesJapanese, etc.), then ensure your application sends UTF-8 encoded text and platform-specific IME events to ImGui.

Dear ImGui (ocornut/imgui) stores all text internally as UTF-8, but the default font only includes Basic Latin glyphs. To render Chinese, Japanese, Cyrillic, or other scripts, you must load an external font and specify which Unicode ranges to rasterize in the font atlas.

How ImFontAtlas Handles Unicode Ranges

The ImFontAtlas API in imgui.cpp and imgui.h manages font loading and glyph rasterization. When you load a font, you must provide a pointer to an array of ImWchar (UTF-16 code points) that defines which characters to bake into the texture atlas. Without this restriction, loading a full CJK font would consume excessive GPU memory.

Built-in Glyph Range Helpers

Dear ImGui provides static helper methods that return pre-defined ranges for common scripts:

  • GetGlyphRangesDefault() – Basic Latin (ASCII)
  • GetGlyphRangesCyrillic() – Cyrillic block (U+0400 … U+04FF)
  • GetGlyphRangesJapanese() – Hiragana, Katakana, and common Kanji
  • GetGlyphRangesKorean() – Hangul syllables
  • GetGlyphRangesChineseFull() – Full CJK Unified Ideographs (approximately 20,000 glyphs)
  • GetGlyphRangesChineseSimplifiedCommon() – Commonly used Simplified Chinese
  • GetGlyphRangesThai() – Thai block
  • GetGlyphRangesVietnamese() – Vietnamese accents

These functions return const ImWchar* arrays that terminate with 0, suitable for passing directly to AddFontFromFileTTF.

Loading Fonts for Chinese, Japanese, and Cyrillic

To display non-Latin characters, load a font file (TTF or OTF) that contains the required glyphs, then specify the range using the helpers above.

Basic Font Loading Example

ImGuiIO& io = ImGui::GetIO();

// Optional: keep the default font as a fallback
io.Fonts->AddFontDefault();

ImFontConfig cfg;
cfg.FontDataOwnedByAtlas = false;  // Application keeps TTF data alive (optional)

// Load Cyrillic support
io.Fonts->AddFontFromFileTTF(
    "fonts/NotoSansCyrillic-Regular.ttf", 
    18.0f, 
    &cfg, 
    io.Fonts->GetGlyphRangesCyrillic()
);

// Load Japanese support
io.Fonts->AddFontFromFileTTF(
    "fonts/NotoSansJP-Regular.otf", 
    18.0f, 
    &cfg, 
    io.Fonts->GetGlyphRangesJapanese()
);

// Optional: Force atlas generation immediately (otherwise happens on first NewFrame)
io.Fonts->Build();

After loading, push the font before drawing text:

ImGui::PushFont(io.Fonts->Fonts.back());  // Use most recently added font
ImGui::Text(u8"中文、にほんご、русский");   // UTF-8 string literal
ImGui::InputText("##input", buf, buf_size); // Accepts UTF-8 input
ImGui::PopFont();

Configuration Considerations

Set cfg.FontDataOwnedByAtlas = false if your application manages the font file memory lifetime. The ImFontConfig structure also allows you to adjust oversampling (OversampleH, OversampleV) and pixel snapping for better rendering quality at small sizes.

Custom Glyph Ranges for Memory Efficiency

Loading GetGlyphRangesChineseFull() can generate an atlas larger than 10 MB and may exceed GPU texture size limits (often 4096 pixels). To load only specific characters, use ImFontGlyphRangesBuilder:

ImVector<ImWchar> ranges;
ImFontGlyphRangesBuilder builder;
builder.AddText(u8"你好世界");     // Add only these four characters
builder.AddRanges(io.Fonts->GetGlyphRangesCyrillic()); // Plus Cyrillic
builder.BuildRanges(&ranges);      // Build the ImWchar array

io.Fonts->AddFontFromFileTTF(
    "fonts/NotoSansSC-Regular.otf",
    18.0f,
    nullptr,
    ranges.Data
);

This approach minimizes memory footprint when you only need a subset of a large CJK font.

Enabling IME Input for CJK Characters

InputText, InputTextMultiline, and InputScalar widgets accept UTF-8 strings natively. However, to type Chinese, Japanese, or Korean characters, your platform backend must forward IME (Input Method Editor) events to Dear ImGui.

Ensure your backend implementation (e.g., imgui_impl_glfw.cpp, imgui_impl_sdl2.cpp, or imgui_impl_win32.cpp) forwards character events:

  • Win32: Handle WM_CHAR and call io.AddInputCharacter(wparam)
  • SDL2: Handle SDL_TEXTINPUT and call io.AddInputCharacterUTF8(event.text.text)
  • GLFW: Handle GLFW_CHAR_CALLBACK (GLFW 3+ handles UTF-8 automatically via glfwSetCharCallback)

Verify that io.ConfigFlags does not include ImGuiConfigFlags_NoKeyboard, as this disables character input processing.

Troubleshooting Non-Latin Character Rendering

Symptom Cause Solution
□ (boxes) appear instead of characters Font lacks glyphs or range not specified Verify font supports the script and pass correct GetGlyphRanges… pointer
Crash or black screen after font loading Atlas texture exceeds GPU max size (4096 or 8192) Increase io.Fonts->TexDesiredWidth (e.g., io.Fonts->TexDesiredWidth = 8192) or use custom ranges
Cannot type CJK characters IME events not forwarded Ensure backend calls io.AddInputCharacter or io.AddInputCharacterUTF8
Garbled text display String encoding is not UTF-8 Ensure source files are saved as UTF-8 and string literals use u8 prefix (C++11)

Summary

  • Dear ImGui uses UTF-8 internally for all text storage and rendering.
  • The default font only contains Basic Latin; you must load external fonts for Chinese, Japanese, Cyrillic, or other scripts.
  • Use ImFontAtlas::AddFontFromFileTTF with range helpers like GetGlyphRangesCyrillic() or GetGlyphRangesJapanese() to rasterize only required glyphs.
  • For large CJK fonts, use ImFontGlyphRangesBuilder to load specific characters and prevent atlas texture overflow.
  • Ensure your platform backend forwards IME events via ImGuiIO::AddInputCharacterUTF8 to enable typing in CJK languages.

Frequently Asked Questions

Why do I see boxes instead of Chinese characters?

You are likely using the default font or forgot to specify the glyph range. The default font only covers ASCII. Load a CJK-compatible font (like Noto Sans CJK) and pass io.Fonts->GetGlyphRangesChineseFull() or GetGlyphRangesChineseSimplifiedCommon() as the fourth parameter to AddFontFromFileTTF.

How do I reduce the memory usage when loading CJK fonts?

Use ImFontGlyphRangesBuilder to specify exactly which characters you need. Instead of loading the full 20,000+ CJK glyphs, add only the specific strings or ranges your application displays. This significantly reduces the atlas texture size.

Can I use multiple fonts simultaneously for different languages?

Yes. Push different fonts using ImGui::PushFont() before drawing text. You can load separate fonts for Cyrillic, Japanese, and Chinese, then switch between them. Alternatively, load a single "Noto Sans" font that covers multiple scripts if you prefer one unified typeface.

Why can't I type Japanese characters in InputText?

Your backend likely isn't forwarding text input events to Dear ImGui. Check that your platform layer calls io.AddInputCharacter() (or the UTF-8 variant) when receiving WM_CHAR (Windows), SDL_TEXTINPUT (SDL), or equivalent events. Also verify that ImGuiConfigFlags_NoKeyboard is not set in io.ConfigFlags.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →