Electronの中華フォントを克服したかった

Electronでは楽にアプリを作れるのは良いのですが、日本語についてはいわゆる中華フォントが表示されてしまうという問題がありました。

これを解決する方法を見つけた、という記事を元々書こうとしていたんですが、つい最近リリースされたv0.36.0で内部のChromeのバージョンが47に上がったせいか、きちんと日本語フォントで表示されるようになっていました。(たぶんChrome 47と同じくMS P ゴシック)

とはいえ、webViewの中身のフォントを外部から変えるといった用途には使えるので一応書き残しておきます。


※2016/01/19 追記 この方法はElectron 0.36 (自分が確認した限りでは0.36.3)では使えなくなっています。Chrome 45から47になる際にフォント関連の動作が変わっているようです。日本語フォントになっただけでも0.35よりは大きく改善されているとはいえ、デフォルトフォントを変えるAPIが無いのはつらいですね...

※2016/01/30 追記 Electron 0.36.5からはデフォルトフォントを変更にできるようになりました。適切に活用していきましょう。->Electronのデフォルトフォントを変更する


ローカルのHTMLファイルをロードするようなElectronアプリの場合、通常通りCSSでfont-familyを指定してやればもちろんフォントを変更できます。 一方、webViewタグを使って外部ページをロードする場合、当然ながら元のサイト側でフォントが指定されることになります。 このとき、sans-serifmonospaceが適用されるとElectronでは中華フォントが使用されてしまっていました。

webContentsやwebViewタグではinsertCSS()を使ってCSSを後から適用できますが、当然ながら全要素のfont-familyを変更するわけにはいきませんので、うまくこの問題を解決できませんでした。

結局のところ今回は、実行環境が日本語Windowsだった場合、font-faceを使ってMeiryo UIとMSゴシックをそれぞれsans-serifmonospaceとして設定する、という方法をとりました。 (Mattermostでは基本的にfont-family: 'Open Sans', sans-serif;でフォント指定されているため)

まずWindowsロケールを判定するためにos-localeをインストールしておきます。

$ npm install os-locale

あとはfont-faceを設定するためにCSSを準備しておき、webViewのDOMの準備ができたタイミングでinsertCSS()でCSSを適用します。

/* jp_fonts.css */
@font-face {
  font-family: sans-serif;
  src: local("Meiryo UI");
}

@font-face {
  font-family: monospace;
  src: local("MS Gothic");
}
/* index.js */
const osLocale = require('os-locale');

webView.addEventListener("dom-ready", function() {
  if (process.platform === 'win32') {
    var applyCssFile = function(cssFile) {
      fs.readFile(cssFile, 'utf8', function(err, data) {
        if (err) {
          console.log(err);
          return;
        }
        webView.insertCSS(data);
      });
    };

    osLocale(function(err, locale) {
      if (err) {
        console.log(err);
        return;
      }
      if (locale === 'ja_JP') {
        applyCssFile(__dirname + '/css/jp_fonts.css');
      }
    });
  }
});

前の記事のデスクトップ通知もそうですが、こんな強引に見える方法が動いてしまうHTML関係っていかがなもんなのかとは感じます。