在 Linux 桌面环境中,中文显示正常,并不代表日文显示也一定正常。中文、日文、韩文虽然都属于 CJK 字符范围,但同一个 Unicode 汉字在不同语言环境下可能有不同的字形习惯。如果系统或网页错误地使用中文字体显示日文内容,页面虽然不会缺字,却会出现字形不协调、假名与汉字风格不统一、整体阅读感很别扭的问题。
本文记录一次日文字体显示异常的排查过程。最终确认,问题并不是系统缺少日文字体,而是由字体优先级、第三方字体残留、网页 CSS 强制指定中文字体等多个因素叠加造成。
一、问题现象
在 Arch Linux 桌面环境中,中文网页显示正常,但日文网页显示明显不自然。具体表现包括:
- 日文汉字像是被中文字体显示;
- 假名与汉字之间风格不协调;
- 标题和正文的视觉效果偏硬、偏中文网页风格;
- 即使系统中已经安装了日文字体,网页仍然没有使用理想的日文字形。
这种问题容易被误认为是“没有安装日语字体”,但实际情况往往更复杂。
二、先确认系统是否安装了日文字体
可以使用 fc-list 查看系统中支持日文的字体:
fc-list :lang=ja
如果系统中已经存在类似以下字体,说明日文字体本身并不缺失:
Noto Sans CJK JP
Noto Serif CJK JP
Noto Sans Mono CJK JP
IPA Gothic
IPA Mincho
Sazanami Gothic
Sazanami Mincho
Source Han Serif JP
这时问题通常不是“没有字体”,而是“系统实际选择了错误的字体”。
三、检查 fontconfig 实际匹配了什么字体
比 fc-list 更关键的是 fc-match。它可以显示当程序请求某种语言和字体族时,fontconfig 实际返回哪一个字体。
检查日语字体匹配:
fc-match 'sans-serif:lang=ja'
fc-match 'serif:lang=ja'
fc-match 'monospace:lang=ja'
异常情况下,结果可能显示为中文字体,例如:
WenQuanYi Zen Hei
这说明系统虽然有日文字体,但日语 sans-serif 或 serif 实际被中文字体抢走了。
理想状态应该接近:
Noto Sans CJK JP
Noto Serif CJK JP
Noto Sans Mono CJK JP
四、清理不再需要的旧中文字体
如果系统中安装了较旧的中文字体包,例如文泉驿字体,它们可能会参与日文字符匹配。
可以先检查:
pacman -Qs '^wqy'
如果已经安装了这些包,并且系统中已经有 Noto CJK 或 Source Han CJK,可以考虑卸载:
sudo pacman -Rns wqy-bitmapfont wqy-microhei wqy-microhei-lite wqy-zenhei
卸载后刷新字体缓存:
sudo fc-cache -frv
再次检查:
fc-match 'sans-serif:lang=ja'
fc-match 'serif:lang=ja'
fc-match 'monospace:lang=ja'
此时日语可能会切换到 IPA Gothic、Sazanami Mincho 等较旧但正确的日文字体。虽然已经比中文字体好,但如果希望显示更现代、更统一,可以继续指定 Noto CJK JP。
五、指定日语优先使用 Noto CJK JP
创建 fontconfig 配置文件,例如:
sudo vim /etc/fonts/conf.d/99-cjk-ja-prefer-noto.conf
写入:
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<match target="pattern">
<test name="lang" compare="contains">
<string>ja</string>
</test>
<test qual="any" name="family" compare="eq">
<string>sans-serif</string>
</test>
<edit name="family" mode="prepend_first" binding="strong">
<string>Noto Sans CJK JP</string>
</edit>
</match>
<match target="pattern">
<test name="lang" compare="contains">
<string>ja</string>
</test>
<test qual="any" name="family" compare="eq">
<string>serif</string>
</test>
<edit name="family" mode="prepend_first" binding="strong">
<string>Noto Serif CJK JP</string>
</edit>
</match>
<match target="pattern">
<test name="lang" compare="contains">
<string>ja</string>
</test>
<test qual="any" name="family" compare="eq">
<string>monospace</string>
</test>
<edit name="family" mode="prepend_first" binding="strong">
<string>Noto Sans Mono CJK JP</string>
</edit>
</match>
</fontconfig>
刷新字体缓存:
sudo fc-cache -frv
确认结果:
fc-match 'sans-serif:lang=ja'
fc-match 'serif:lang=ja'
fc-match 'monospace:lang=ja'
理想结果:
Noto Sans CJK JP
Noto Serif CJK JP
Noto Sans Mono CJK JP
六、顺便整理简体中文字体匹配
日语修复后,也可以检查简体中文字体匹配:
fc-match 'sans-serif:lang=zh-cn'
fc-match 'serif:lang=zh-cn'
fc-match 'monospace:lang=zh-cn'
有时会出现 serif:lang=zh-cn 也匹配到微软雅黑的情况。这并不会造成缺字,但从字体族逻辑上并不理想,因为微软雅黑是无衬线字体,不应该接管 serif。
可以创建简体中文优先规则:
sudo vim /etc/fonts/conf.d/99-cjk-zhcn-prefer-noto.conf
写入:
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<match target="pattern">
<test name="lang" compare="contains">
<string>zh-cn</string>
</test>
<test qual="any" name="family" compare="eq">
<string>sans-serif</string>
</test>
<edit name="family" mode="prepend_first" binding="strong">
<string>Noto Sans CJK SC</string>
</edit>
</match>
<match target="pattern">
<test name="lang" compare="contains">
<string>zh-cn</string>
</test>
<test qual="any" name="family" compare="eq">
<string>serif</string>
</test>
<edit name="family" mode="prepend_first" binding="strong">
<string>Noto Serif CJK SC</string>
</edit>
</match>
<match target="pattern">
<test name="lang" compare="contains">
<string>zh-cn</string>
</test>
<test qual="any" name="family" compare="eq">
<string>monospace</string>
</test>
<edit name="family" mode="prepend_first" binding="strong">
<string>Noto Sans Mono CJK SC</string>
</edit>
</match>
</fontconfig>
刷新缓存后,理想结果为:
zh-cn sans-serif → Noto Sans CJK SC
zh-cn serif → Noto Serif CJK SC
zh-cn monospace → Noto Sans Mono CJK SC
这样中日文字体就可以各自走对应地区的字形。
七、清理第三方程序残留字体
某些远程桌面或第三方软件可能会在系统字体目录中放入自己的 CJK 字体。这类字体不一定有问题,但如果被 fontconfig 扫描,可能会增加字体匹配的不确定性。
可以用类似方式检查:
fc-list | grep -i 软件名
如果确认相关字体目录并非系统必要字体,并且希望彻底清理,可以删除对应字体目录,然后刷新缓存:
sudo rm -rf /系统字体目录/第三方字体目录
sudo fc-cache -frv
再次确认:
fc-list | grep -i 软件名 || echo "No related fonts found by fontconfig."
如果输出显示没有相关字体,说明该第三方字体已经不再参与 fontconfig 匹配。
八、系统字体修好后,网页仍异常的原因
即使系统层面的 fc-match 已经完全正确,网页显示仍可能异常。原因是网页 CSS 可以强行指定字体。
例如某些网站或博客主题可能写了类似规则:
*:not([class*="icon"]):not(i) {
font-family: Segoe UI, "Microsoft Yahei" !important;
}
这条规则非常强,会让页面几乎所有元素都强制使用 Segoe UI 和 Microsoft YaHei。由于带有 !important,它会覆盖很多正常字体匹配逻辑。
此时即使 Linux 系统中已经把日语匹配到 Noto Sans CJK JP,浏览器仍然可能按网页 CSS 使用微软雅黑显示日文。
可以通过浏览器开发者工具确认:
- 右键点击网页正文;
- 选择 Inspect / 检查;
- 查看 Computed;
- 查找
font-family或 Rendered Fonts。
如果看到:
font-family: "Segoe UI", "Microsoft YaHei"
说明问题来自网页 CSS,而不是系统字体。
九、修正网页 CSS
如果网站同时包含中文和日文内容,不建议用 * 全局强制微软雅黑。更合理的做法是:
body,
.entry-content,
.entry-content p,
.entry-content li,
.entry-content h1,
.entry-content h2,
.entry-content h3,
.entry-content h4,
.entry-content h5,
.entry-content h6 {
font-family: "Segoe UI", "Noto Sans CJK SC", "Microsoft YaHei", sans-serif;
}
对于日语文章,可以单独指定日文字体。例如针对某一篇日语文章:
body.postid-xxxx .entry-content,
body.postid-xxxx .entry-content *:not([class*="icon"]):not(i) {
font-family: "Noto Sans CJK JP", "Noto Sans JP", "Yu Gothic", "Hiragino Sans", "Meiryo", sans-serif !important;
}
代码块可以单独指定等宽字体:
body.postid-xxxx .entry-content pre,
body.postid-xxxx .entry-content code {
font-family: "Noto Sans Mono CJK JP", "Source Code Pro", "Ubuntu Mono", monospace !important;
}
如果以后经常发布日语文章,更推荐使用统一 class:
.ja-article,
.ja-article *:not([class*="icon"]):not(i) {
font-family: "Noto Sans CJK JP", "Noto Sans JP", "Yu Gothic", "Hiragino Sans", "Meiryo", sans-serif !important;
}
这样可以只影响日语内容,而不破坏中文文章的字体风格。
十、最终效果
完成系统字体整理和网页 CSS 修正后,日语页面的显示明显改善:
- 日文汉字变为日本字形;
- 假名与汉字风格统一;
- 标题和正文更接近日语网页的阅读习惯;
- 中文文章仍可保持简体中文字体;
- 系统层面的 CJK 字体匹配更加清晰。
最终理想结构可以概括为:
日语 sans-serif → Noto Sans CJK JP
日语 serif → Noto Serif CJK JP
日语 monospace → Noto Sans Mono CJK JP
简体中文 sans-serif → Noto Sans CJK SC
简体中文 serif → Noto Serif CJK SC
简体中文 monospace → Noto Sans Mono CJK SC
结语
Linux 下的 CJK 字体问题并不只是“有没有安装字体”这么简单。对于中文和日文混合使用的环境,真正关键的是:
- 系统中是否有合适的 CJK 字体;
- fontconfig 是否按语言正确匹配;
- 是否有旧字体或第三方字体干扰;
- 网页 CSS 是否强制指定了错误字体;
- 页面语言标记和文章内容语言是否一致。
当系统层面的字体匹配和网页层面的 CSS 都整理好之后,日语显示效果会有明显提升。对于经常阅读或发布日语内容的 Linux 用户来说,单独处理 ja 和 zh-cn 的字体优先级,是非常值得做的一项基础配置。