Better font selection for kanji

So, I discovered a problem where if I had notes for Japanese and then say Simplified Chinese, Anki could display the incorrect kanji according to my system localisation settings. So, after searching a bit, I couldn’t find or come up with a nice solution.

Using Noto Sans CJK/Noto Serif CJK, there’s 5 variants for CJK characters: SC, TC, HK, JP and KR. I don’t really want to maintain 5 separate note types for each of these font variants, for each of my custom note types.

So, currently I added a Language field which accepts a language code from a list of common language codes. This field is then parsed so I can add an @font-face rule to overwrite Noto Sans CJK/Noto Serif CJK (by default, I’ve set it to Japanese).

(An idea that would make this much more pleasant is an addon that prefills contents of fields when adding to certain decks, say adding to Japanese would set Language to “jp-JA”. this aside…)

I’m wondering if there’s a better way to approach this problem because to me, embedding CSS in JS strings like this is ugly.

<!-- front side -->
<div id="language" class="hide">{{Language}}</div>

<!-- cardside stylesheet, different from Anki's card stylesheet -->
<style id="body-style"></style>

<script>
 var languages = document.getElementById("language").innerText.split(" ");
 /* Render correct kanji */
 languages.forEach(function (language) {
     var lang = language.split("-");
     var ss = document.querySelector("#body-style");
     if (language == "zh-HK") {
         ss.append(
`@font-face {
 font-family: Noto Sans CJK;
 src: local(\"Noto Sans CJK HK\");
}\n
@font-face {
 font-family: Noto Serif CJK;
 src: local(\"Noto Serif CJK HK\");
}\n`
         );
     } else if (language == "zh-TW") {
         ss.append(
`@font-face {
 font-family: Noto Sans CJK;
 src: local(\"Noto Sans CJK TC\");
}\n
@font-face {
 font-family: Noto Serif CJK;
 src: local(\"Noto Serif CJK TC\");
}\n`
         );
     } else if (lang[0] == "zh") {
         ss.append(
`@font-face {
 font-family: Noto Sans CJK;
 src: local(\"Noto Sans CJK SC\");
}\n
@font-face {
 font-family: Noto Serif CJK;
 src: local(\"Noto Serif CJK SC\");
}\n`
         );
     } else if (lang[0] == "ko") {
         ss.append(
`@font-face {
 font-family: Noto Sans CJK;
 src: local(\"Noto Sans CJK KR\");
}\n
@font-face {
 font-family: Noto Serif CJK;
 src: local(\"Noto Serif CJK KR\");
}\n`
         );
     }
 });
</script>
/* card style */
.card {
    font-family: Noto Sans, Noto Sans CJK, sans;
}

/* default to Japanese kanji */
@font-face {
    font-family: Noto Sans CJK;
    src: local("Noto Sans CJK JP");
}

Instead of assigning a font to the whole card, I use the lang attribute to set it accordingly for single HTML elements.
If you use the same notetype for various languages, you can either set lang in the note HTML, or try to automate that with JS as you’ve done above. But there’s no need to use a separate “Language” field or an add-on if you want to set it depending on the current deck. You can use the special field {{Deck}} (or maybe {{Tags}}) if its name contains the appropriate language.

4 Likes

Sounds like a much more cleaner solution! thanks a lot rumo! i’ve neglected the special fields it seems.

1 Like