在 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-serifserif 实际被中文字体抢走了。

理想状态应该接近:

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 使用微软雅黑显示日文。

可以通过浏览器开发者工具确认:

  1. 右键点击网页正文;
  2. 选择 Inspect / 检查;
  3. 查看 Computed;
  4. 查找 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 用户来说,单独处理 jazh-cn 的字体优先级,是非常值得做的一项基础配置。

Leave a Reply

Your email address will not be published. Required fields are marked *