PlantUML 中文/日文/Emoji 渲染踩坑与字体配置

puml.online

PlantUML 默认字体 DejaVu Sans 只含拉丁字符。中文 / 日文 / 韩文 / Emoji 渲染要么是方块要么是缺失。这篇是字体配置实战 + CI 环境搭建 + 多语言混排。

三个常见症状

症状 1:中文渲染成 □□□

1
2
3
4
@startuml
skinparam defaultFontName "DejaVu Sans"
Alice -> Bob: 你好世界
@enduml

输出 SVG 里中文是 三个空格方块DejaVu Sans 不含 CJK 字符

症状 2:Emoji 显示成黑白字符

1
2
3
@startuml
Alice -> Bob: 🚀 部署成功 🎉
@enduml

Emoji 变成 < > 这种字符,不是彩色图标。DejaVu Sans 不含 Emoji 字体

症状 3:日文假名乱码

1
2
3
@startuml
note left: こんにちは世界
@enduml

部分假名能显示,部分显示不出来——字体里只有部分日文字符集(如只有 Hiragana,没有 Katakana)。

修法 1:换字体(server / Docker 端)

Linux 服务器装 CJK 字体

1
2
3
4
5
6
7
8
# Debian/Ubuntu
sudo apt-get install -y fonts-noto-cjk fonts-noto-cjk-extra

# RHEL/CentOS
sudo yum install -y google-noto-sans-cjk-fonts

# Alpine(精简镜像常用)
apk add --no-cache font-noto-cjk

装完 重启 plantuml server 让它刷新字体缓存。

Docker 镜像里装字体

修改 Dockerfile:

1
2
3
4
5
6
7
8
9
10
11
FROM plantuml/plantuml-server:tomcat

USER root

RUN apt-get update && \
apt-get install -y --no-install-recommends \
fonts-noto-cjk \
fonts-noto-color-emoji && \
rm -rf /var/lib/apt/lists/*

USER plantuml
1
docker build -t my-plantuml:cn .

PlantUML 指定字体

1
2
3
4
5
6
@startuml
skinparam defaultFontName "Noto Sans CJK SC"
skinparam defaultFontSize 14

Alice -> Bob: 你好世界
@enduml

或者 CLI 参数:

1
plantuml -SdefaultFontName="Noto Sans CJK SC" diagram.puml

修法 2:Emoji 字体

装 Noto Color Emoji

1
2
3
4
5
6
# Debian/Ubuntu
sudo apt-get install -y fonts-noto-color-emoji

# 验证字体装好
fc-list | grep -i emoji
# /usr/share/fonts/truetype/noto/NotoColorEmoji.ttf: Noto Color Emoji:style=Regular

PlantUML 配置

PlantUML 用 <fontconfig> 自动匹配字体,但需要在 diagram 里显式说明:

1
2
3
4
5
6
7
@startuml
skinparam defaultFontName "Noto Sans CJK SC"
skinparam sequenceMessageAlign center

Alice -> Bob: 🚀 部署成功 🎉
note right: 中文注释 Noto Color Emoji
@enduml

Emoji 会用 Noto Color Emoji 字体,中文用 Noto Sans CJK SC。两个字体并存,fontconfig 自动 fallback。

但有个坑:PlantUML 不支持单字符字体切换——同一行文字如果同时含中文和 Emoji,Emoji 可能用 CJK 字体渲染(没有对应 glyph) → Emoji 显示成方框。

修法——用 <font> 标签隔离:

1
Alice -> Bob: <font color=red>🚀</font> 部署成功 <font color=green>🎉</font>

或者干脆分开两行:

1
2
3
Alice -> Bob: 🚀
Alice -> Bob: 部署成功
Alice -> Bob: 🎉

修法 3:多语言混排

中英日韩 + Emoji + 阿拉伯文 + 拉丁字符混合时,字体 fallback 链至关重要

Linux fontconfig 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- /etc/fonts/conf.d/99-cjk.conf -->
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<alias>
<family>sans-serif</family>
<prefer>
<family>Noto Sans CJK SC</family>
<family>Noto Sans CJK TC</family>
<family>Noto Sans CJK JP</family>
<family>Noto Sans CJK KR</family>
<family>Noto Color Emoji</family>
<family>DejaVu Sans</family>
</prefer>
</alias>
</fontconfig>

<prefer> 里字体按优先级匹配:中文走 SC,Emoji 走 Color Emoji,英文走 DejaVu。

PlantUML 多字体 fallback

PlantUML 1.2024+ 支持 <font> 嵌套:

1
2
3
4
@startuml
skinparam defaultFontName "Noto Sans CJK SC,DejaVu Sans"
Alice -> Bob: 你好 Hello 世界 🚀
@enduml

逗号分隔多个字体名,PlantUML 用 fontconfig 找第一个能渲染的字体。

修法 4:Mac/Windows 本地渲染

本地 hexo 博客 hexo generate 时,如果用 plantuml CLI 渲染,字体也要装:

1
2
3
4
5
# macOS — 系统自带 PingFang SC,直接可用
fc-list | grep -i "pingfang"

# Windows — 装思源黑体
winget install Noto.Sans.CJK

hexo-renderer-plantuml 调用的 plantuml 默认用 <system> 字体,在 macOS 自动用 PingFang,在 Windows 自动用 Microsoft YaHei。

CI 环境

GitHub Actions 默认 ubuntu-latest 没有 CJK 字体。要装:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# .github/workflows/diagrams.yml
jobs:
render:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install CJK fonts
run: |
sudo apt-get update
sudo apt-get install -y fonts-noto-cjk fonts-noto-color-emoji
- name: Render diagrams
run: |
docker run --rm -v $(pwd):/data \
-e LANG=en_US.UTF-8 \
plantuml/plantuml \
-tsvg -failfast2 /data/docs/diagrams/*.puml

LANG=en_US.UTF-8 让 plantuml 用 UTF-8 字符集处理输入——否则可能用 ASCII 字符集导致中文乱码。

字体子集化(减小字体包)

Noto Sans CJK SC 全字符集 ~20MB。镜像里塞这玩意太重。

只装常用字符子集:

1
2
3
4
5
6
7
# 用 fonttools 提取子集
pip install fonttools brotli
pyftsubset NotoSansCJKsc-Regular.otf \
--text="$(cat docs/diagrams/*.puml | grep -oP '[\u4e00-\u9fff]+' | sort -u | tr -d '\n')" \
--output-file=NotoSansCJKsc-SC-subset.otf

# 通常从 20MB 减到 200KB-2MB

Dockerfile 装子集:

1
2
3
4
FROM plantuml/plantuml-server:tomcat

COPY NotoSansCJKsc-SC-subset.otf /usr/share/fonts/truetype/noto/
RUN fc-cache -fv

字号 / 行高优化

中文 CJK 字符宽度跟英文字符不同,PlantUML 默认行高会导致中英混排错位

1
2
3
4
5
6
7
8
9
10
11
@startuml
skinparam defaultFontName "Noto Sans CJK SC"
skinparam defaultFontSize 14
skinparam dpi 150
skinparam Padding 5

note left
这是中文注释
Mixed 中英文 line
end note
@enduml

Padding 5 让方框内边距足够容纳中文,dpi 150 输出更清晰(默认 96)。

实战 debug 流程

1
2
3
4
5
6
7
8
9
10
11
# 1. 验证字体装了
fc-list | grep -i "noto sans cjk"

# 2. 验证 plantuml 能识别字体
echo 'alice -> bob: 你好' | plantuml -pipe -tsvg > /tmp/test.svg
grep -o "Noto Sans CJK SC\|DejaVu Sans" /tmp/test.svg | sort -u
# 应该输出 Noto Sans CJK SC

# 3. 验证 fontconfig fallback 链
fc-match "Noto Sans CJK SC"
# /usr/share/fonts/.../NotoSansCJKsc-Regular.otf: "Noto Sans CJK SC" "Regular"

如果 fc-match 输出不是预期的字体 → fontconfig 配置错了,检查 /etc/fonts/conf.d/ 下的 conf 文件优先级。

总结

场景 修法
中文/日文变方块 fonts-noto-cjk,PlantUML 指定 defaultFontName
Emoji 显示成字符 fonts-noto-color-emoji,和 CJK 字体同时存在
中英混排错位 Padding 5dpi 150
CI 渲染中文乱码 apt 装字体 + LANG=en_US.UTF-8
Docker 镜像太大 pyftsubset 提取 puml 实际用到的字符子集
多语言混排 fontconfig <prefer> 链,按优先级匹配字体

最小配置 —— 服务器装 fonts-noto-cjk + fonts-noto-color-emoji,重启 plantuml,搞定 95% 多语言需求。

  • 标题: PlantUML 中文/日文/Emoji 渲染踩坑与字体配置
  • 作者: puml.online
  • 创建于 : 2026-07-30 16:50:00
  • 更新于 : 2026-08-14 21:34:29
  • 链接: https://puml.online/blog/plantuml-cjk-emoji-encoding/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。