My contributions to the Japanese learning community. For questions and support, please make a thread in the questions forum in TheMoeWay. For suggestions please mention @Marv.
Contributions are welcome, feel free to open a pull request. Note that there is a Prettier config file in the repo for auto formatting with the extension.
In addition, the Markdown All in One extension can be used to automatically generate and update a table of contents as well as assist in markdown editing.
These are absolutely essential.
Much thanks to:
I sometimes get asked about what frequency dictionaries to use and the differences between them, so here are a few essential dictionaries I would recommend.
The balanced corpus of contemporary written Japanese (BCCWJ) is Japan’s first 100 million words balanced corpus. It consists of three subcorpora (publication subcorpus, library subcorpus, and special-purpose subcorpus) and covers a wide range of text registers including books in general, magazines, newspapers, governmental white papers, best-selling books, an internet bulletin-board, a blog, school textbooks, minutes of the national diet, publicity newsletters of local governments, laws, and poetry verses.
When reading and adding cards from the content you're reading, you'll come across a variety of words with varying degrees of usefulness. Especially as a beginner, you'll want to learn the useful words as soon as possible and learn the less useful words later. With this we can sort a backlog of mined cards by frequency using various installed Yomichan frequency lists.
This handlebar for Yomichan will add a {freq}
field that will use your installed frequency dictionaries to send a numerical frequency value to Anki depending on the sort option applied, with the default being the (recommended) harmonic mean.
First, in your Anki card template create a new field for frequency, we can name this Frequency
or whatever you like.
Then in Yomichan options, insert the following handlebars code at the end of the menu in Configure Anki card templates...
.
freq
Handlebar[!NOTE] This is the same handlebar that is used in jp-mining-note, but with a different name and with the options included. If you want to use it with jp-mining-note, you can copy the code below and rename
freq
in the first line tojpmn-frequency-sort
, then remove the options section.
{{#*inline "freq"}}
{{~! Frequency sort handlebars: v24.01.10.1 ~}}
{{~! The latest version can be found at https://github.com/MarvNC/JP-Resources#freq-handlebar ~}}
{{~#scope~}}
{{~! Options ~}}
{{~#set "opt-ignored-freq-dict-regex"~}} ^(JLPT.*)|(HSK.*)$ {{~/set~}}
{{~#set "opt-ignored-freq-value-regex"~}} ❌ {{~/set~}}
{{~#set "opt-keep-freqs-past-first-regex"~}} ^()$ {{~/set~}}
{{~set "opt-no-freq-default-value" 9999999 ~}}
{{~set "opt-freq-sorting-method" "harmonic" ~}} {{~! "min", "first", "avg", "harmonic" ~}}
{{~set "opt-grammar-override" true ~}}
{{~set "opt-grammar-override-value" 0 ~}}
{{~#set "opt-grammar-override-dict-regex"~}} ^(日本語文法辞典\(全集\)|毎日のんびり日本語教師|JLPT文法解説まとめ|どんなときどう使う 日本語表現文型辞典|絵でわかる日本語)$ {{~/set~}}
{{~! End of options ~}}
{{~! Do not change the code below unless you know what you are doing. ~}}
{{~set "result-freq" -1 ~}} {{~! -1 is chosen because no frequency dictionaries should have an entry as -1 ~}}
{{~set "prev-freq-dict" "" ~}}
{{~set "t" 1 ~}}
{{~set "found-grammar-dict" false ~}}
{{~! search for grammar dictionary ~}}
{{~#each definition.definitions~}}
{{~#set "rx-match-grammar-dicts" ~}}
{{~#regexMatch (get "opt-grammar-override-dict-regex") "u"~}}{{this.dictionary}}{{~/regexMatch~}}
{{/set~}}
{{~! rx-match-grammar-dicts is not empty if a grammar dictionary was found ~}}
{{~#if (op "!==" (get "rx-match-grammar-dicts") "") ~}}
{{~set "found-grammar-dict" true ~}}
{{/if~}}
{{~/each~}}
{{~! Additional case when "Result grouping mode" is set to "No Grouping"~}}
{{~#set "rx-match-grammar-dicts" ~}}
{{~#regexMatch (get "opt-grammar-override-dict-regex") "u"~}}{{this.definition.dictionary}}{{~/regexMatch~}}
{{/set~}}
{{~! rx-match-grammar-dicts is not empty if a grammar dictionary was found ~}}
{{~#if (op "!==" (get "rx-match-grammar-dicts") "") ~}}
{{~set "found-grammar-dict" true ~}}
{{/if~}}
{{~#each definition.frequencies~}}
{{~! rx-match-ignored-freq is not empty if ignored <=> rx-match-ignored-freq is empty if not ignored ~}}
{{~#set "rx-match-ignored-freq" ~}}
{{~#regexMatch (get "opt-ignored-freq-dict-regex") "u"~}}{{this.dictionary}}{{~/regexMatch~}}
{{/set~}}
{{~#set "rx-match-ignored-value" ~}}
{{~#regexMatch (get "opt-ignored-freq-value-regex") "u"~}}{{this.frequency}}{{~/regexMatch~}}
{{/set~}}
{{~#if (op "&&" (op "===" (get "rx-match-ignored-freq") "") (op "===" (get "rx-match-ignored-value") ""))~}}
{{~!
only uses the 1st frequency of any dictionary.
For example, if JPDB lists 440 and 26189㋕, only the first 440 will be used.
~}}
{{~set "read-freq" false ~}}
{{~#if (op "!==" (get "prev-freq-dict") this.dictionary ) ~}}
{{~set "read-freq" true ~}}
{{~set "prev-freq-dict" this.dictionary ~}}
{{/if~}}
{{~#if (op "!" (get "read-freq") ) ~}}
{{~#set "rx-match-keep-freqs" ~}}
{{~#regexMatch (get "opt-keep-freqs-past-first-regex") "u"~}}{{this.dictionary}}{{~/regexMatch~}}
{{/set~}}
{{~! rx-match-keep-freqs is not empty if keep freqs ~}}
{{~#if (op "!==" (get "rx-match-keep-freqs") "") ~}}
{{~set "read-freq" true ~}}
{{/if~}}
{{/if~}}
{{~#if (get "read-freq") ~}}
{{~#set "numericFrequencyMatch"}}{{~#regexMatch "\d+" ""}}{{~this.frequency~}}{{/regexMatch~}}{{/set~}}
{{~set "f" (op "+" (get "numericFrequencyMatch")) ~}}
{{~#if (op "===" (get "opt-freq-sorting-method") "min") ~}}
{{~#if
(op "||"
(op "===" (get "result-freq") -1)
(op ">" (get "result-freq") (get "f"))
)
~}}
{{~set "result-freq" (op "+" (get "f")) ~}}
{{~/if~}}
{{~else if (op "===" (get "opt-freq-sorting-method") "first") ~}}
{{~#if (op "===" (get "result-freq") -1) ~}}
{{~set "result-freq" (get "f") ~}}
{{~/if~}}
{{~else if (op "===" (get "opt-freq-sorting-method") "avg") ~}}
{{~#if (op "===" (get "result-freq") -1) ~}}
{{~set "result-freq" (get "f") ~}}
{{~else~}}
{{~!
iterative mean formula (to prevent floating point overflow):
$S_{(t+1)} = S_t + \frac{1}{t+1} (x - S_t)$
- example java implementation: https://stackoverflow.com/a/1934266
- proof: https://www.heikohoffmann.de/htmlthesis/node134.html
~}}
{{~set "result-freq"
(op "+"
(get "result-freq")
(op "/"
(op "-"
(get "f")
(get "result-freq")
)
(get "t")
)
)
}}
{{~/if~}}
{{~set "t" (op "+" (get "t") 1) ~}}
{{~else if (op "===" (get "opt-freq-sorting-method") "harmonic") ~}}
{{~#if (op ">" (get "f") 0) ~}} {{~! ensures only positive numbers are used ~}}
{{~#if (op "===" (get "result-freq") -1) ~}}
{{~set "result-freq" (op "/" 1 (get "f")) ~}}
{{~else ~}}
{{~set "result-freq"
(op "+"
(get "result-freq")
(op "/" 1 (get "f"))
)
}}
{{~set "t" (op "+" (get "t") 1) ~}}
{{~/if~}}
{{~/if~}}
{{~else if (op "===" (get "opt-freq-sorting-method") "debug") ~}}
{{ this.dictionary }}: {{ this.frequency }} -> {{ get "f" }} <br>
{{~else~}}
(INVALID opt-freq-sorting-method value)
{{~/if~}}
{{~/if~}}
{{~/if~}}
{{~/each~}}
{{~! (x) >> 0 apparently floors x: https://stackoverflow.com/a/4228528 ~}}
{{~#if (op "===" (get "result-freq") -1) ~}}
{{~set "result-freq" (get "opt-no-freq-default-value") ~}}
{{~ else if (op "===" (get "opt-freq-sorting-method") "avg") ~}}
{{~set "result-freq"
(op ">>" (get "result-freq") 0 )
~}}
{{~ else if (op "===" (get "opt-freq-sorting-method") "harmonic") ~}}
{{~set "result-freq"
(op ">>"
(op "*"
(op "/" 1 (get "result-freq"))
(get "t")
)
0
)
~}}
{{~/if~}}
{{~! override final result if grammar dictionary ~}}
{{~#if (
op "&&"
(op "===" (get "found-grammar-dict") true)
(op "===" (get "opt-grammar-override") true)
)
~}}
{{~set "result-freq" (get "opt-grammar-override-value") ~}}
{{/if}}
{{~get "result-freq"~}}
{{~/scope~}}
{{/inline}}
In Configure Anki card format...
, we may need to refresh the card model for the new field to show up.
When your frequency field shows up, type in {freq}
in its value box to use the handlebar.
freq
SettingsThe default settings within the freq
handlebars code should work for most people.
However, it can be customized if desired.
To access the settings, head back to Yomichan's templates (Yomichan options → Anki
→ Configure Anki card templates...
),
and view the lines right below {{#*inline "freq"}}
.
Use the AnkiAutoReorder addon to have your backlog sort automatically on refresh.
search_to_sort
) and your sort_field
into the addon's config (Tools > Addons > AutoReorder > Config
).
is:new
.Tools > Reposition Cards
. Remember to do this every day after adding new cards.I also recommend installing the Advanced Browser addon to display the frequency field in Anki's browse page.
Below: right click the column headers at the top with Advanced Browser installed to select new fields to be displayed.
Alternatively, after installing Advanced Browser, you could sort by the frequency field and press ctrl + a
then ctrl + shift + s
to select all cards and reorder.
If you already have a large backlog of old cards without frequency values, you might need to fill in these values first or they won't be sorted. There are two methods listed below to do exactly that. The command line method runs much faster than the Anki method, but requires some command line knowledge to pull off.
Of course, you could just opt to finish reviewing these cards first instead of backfilling the old cards.
Warning: Make sure to backup your collection before trying either method below.
Differences between the backfill .txt files
JPDB.txt
- Japanese list from jpdb.iocc100.txt
- The CC100 dataset as described in the Frequency Dictionaries section.vnsfreqSTARS.txt
and vnsfreq.txt
- Japanese frequency lists from visual novelsBLCUcoll.txt
and BLCUlit.txt
- Chinese frequency lists from colloquial and literary text from the BLCU BCC Corpus.SUBTLEX-CH.txt
- Chinese frequency list based on movie/TV subtitles from SUBTLEX-CH.Note that the Japanese ones are selected by default when backfilling via the command line; you will have to use the --freq-lists
option to specify other lists.
If you frequently make cards that don't contain frequencies, such as sentence or grammar cards, you won't be able to pull frequencies from dictionaries. If you tag all of these cards specifically, you can use this plugin to generate random frequencies for these cards.
In the JP Mining Note Anki note type, there is also a FrequenciesStylized field for displaying the values from various frequency dictionaries on the front of the card. Due to the specific formatting requirements of this field, it cannot be backfilled with the above methods. A separate script is provided in the frequencies/frequenciesstylized
folder for this purpose.
Warning: As always, back up your entire collection before performing any steps from this section
Before running the script, you will need to configure the list of frequency dictionaries to be used:
The set of frequency dictionaries to use can be configured by editing the dict_names.py
file. The default values in this file are shown below:
dict_names = [
('JPDB-stylized.txt', 'JPDB'),
('../vnsfreq.txt', 'VN Freq'),
('JLPT-stylized.txt', 'JLPT')
]
The order of the dictionaries in this list determines the order that the frequencies will appear in the FrequenciesStylized field. Within each entry, the first parameter is the relative filepath to the frequency list, and the second parameter is the display name you want to use for that dictionary.
For example, the above configuration produces the following result for 返事:
If you change the dict_names.py
file to:
dict_names = [
('../vnsfreq.txt', 'VN Freq'),
('JPDB-stylized.txt', 'jpdb'),
('JLPT-stylized.txt', 'jlpt')
]
Then it will now produce this output: (note the lowercase dictionary names)
Note the ../
in the filepath for the VN Freq dictionary. This script can use any of the frequency lists that are used by backfill.py
. However, if there is a stylized version of a frequency list, then it is highly recommended that you use that one, rather than the simpler version. This is because the stylized version includes additional formatting, such as JPDB's ㋕ marker for kana frequencies.
Stylized versions of frequency lists also include the reading for each word, so if your cards have the WordReadingHiragana
field filled in, then the script can ensure that only the frequencies for the correct reading are used. If your notes do not have the WordReadingHiragana
field filled, then it's highly recommended that you fill it using the instructions on the JP Mining Note docs.
Once you have configured the list of dictionaries to use, you can run the script. The simplest way to run this script is to navigate into the frequencies/frequenciesstylized
folder, and run:
# Linux users might have to use `python3` instead of `python`.
python backfill-stylized.py
This will search your collection for all notes of type JP Mining Note
with an empty FrequenciesStylized
field. It will then fill those fields with the appropriate frequency information as determined by your configuration in dict_names.py
. It will also tag every note it modifies with the tag backfill-stylized
. There are two options that can be used with this script:
If you have never edited the FrequenciesStylized
field on a note, then it is probably completely empty, and backfill-stylized.py
will be able to find the note.
However, in some cases, the FrequenciesStylized
field might look empty, when in fact it has some hidden HTML tags in it. In this case, the script will not be able to find these notes, since it is only looking for notes where this field is empty.
FrequenciesStylized looks empty |
But it actually has hidden HTML elements |
---|---|
You can clear this HTML directly by clicking on the HTML toggle button marked in the above image. Then just delete the HTML from the editor.
If you need to completely clear the FrequenciesStylized
field for several cards at once, first select all the relevent cards in the Anki browser. Then, go to Notes -> Find and Replace...
and enter the options shown below.
WARNING: Unless you know exactly what you're doing, only use the options shown below. Using different options has the potential to delete an arbitrary amount of information from an arbitrary number of cards in your collection
After clicking OK, the FrequenciesStylized
field for all selected notes will be completely emptied.
When adding cards from VNs, we might find some risque content that we still want to look at while reviewing because it's cute. However, you might review in places where you don't always want other people to see your cards. Using this card template, we can blur media in Anki and have the option persist throughout a review session.
x | Blur disabled | Blur enabled |
---|---|---|
SFW | ||
NSFW |
Media: ハミダシクリエイティブ © まどそふと
Decide on a tag for NSFW cards. I use -NSFW
so the tag is sorted first for easy access. If you choose something else you'll need to replace all instances of -NSFW
in this guide with your tag name (with ctrl + h
in a text editor or an online tool).
Tag your NSFW cards with this tag in Anki (see ShareX Hotkey).
Download the anki-persistence script (minified.js
or script.js
) from here. Then rename it __persistence.js
and place it in your Anki user/media folder.
{{Picture}}
to match the name of the field that contains your media.<div id="main_image" class="{{Tags}}">
<a onclick="toggleNsfw()">{{Picture}}</a>
</div>
<script src="https://github.com/MarvNC/JP-Resources/raw/main/__persistence.js"></script>
<script>
// nsfw https://github.com/MarvNC/JP-Resources
(function () {
const nsfwDefaultPC = true;
const nsfwDefaultMobile = false;
const imageDiv = document.getElementById('main_image');
const image = imageDiv.querySelector('a img');
if (!image) {
imageDiv.parentNode.removeChild(imageDiv);
}
let loaded = false;
setInterval(() => {
if (!loaded) {
if (typeof Persistence === 'undefined') {
return;
}
loaded = true;
let onMobile = document.documentElement.classList.contains('mobile');
let nsfwAllowed = onMobile ? nsfwDefaultMobile : nsfwDefaultPC;
if (Persistence.isAvailable() && Persistence.getItem('nsfwAllowed') == null) {
Persistence.setItem('nsfwAllowed', nsfwAllowed);
} else if (Persistence.isAvailable()) {
nsfwAllowed = Persistence.getItem('nsfwAllowed');
}
setImageStyle(nsfwAllowed);
}
}, 50);
})();
function toggleNsfw() {
if (Persistence.isAvailable()) {
let nsfwAllowed = !!Persistence.getItem('nsfwAllowed');
nsfwAllowed = !nsfwAllowed;
Persistence.setItem('nsfwAllowed', nsfwAllowed);
setImageStyle(nsfwAllowed);
} else {
setImageStyle(undefined, true);
}
}
function setImageStyle(nsfwAllowed = undefined, toggle = false) {
const imageDiv = document.getElementById('main_image');
const image = imageDiv.querySelector('img');
if (nsfwAllowed != undefined) {
imageDiv.classList.toggle('nsfwAllowed', nsfwAllowed);
} else if (toggle) {
imageDiv.classList.toggle('nsfwAllowed');
}
}
</script>
Then in your card styling paste in the following css, making sure to replace -NSFW
with your tag name.
#main_image.nsfwAllowed {
border-top: 2.5px dashed fuchsia !important;
}
#main_image {
border-top: 2.5px solid springgreen;
}
#main_image img {
cursor: pointer;
}
#main_image.-NSFW {
border-left: 2.5px dashed red;
border-right: 2.5px dashed red;
border-bottom: 2.5px dashed red;
}
#main_image.nsfwAllowed.-NSFW {
border-top: 2.5px dashed red !important;
}
#main_image.-NSFW img {
filter: blur(30px);
}
#main_image.nsfwAllowed img {
filter: blur(0px) !important;
}
During a review session, you can click/tap the image to toggle card blurring. When the blurring is enabled, there will be a solid green line at the top of the image. When blurring is not enabled, there will be a fuchsia dotted line, and when the card is NSFW the borders will be dotted red. This option will persist throughout a review session but the setting will reset after exiting the session.
In the code we pasted in the template there are variables that can change whether blurring is enabled by default on desktop/mobile separately; the thought being that this script is primarily intended for reviewing on a phone. These variables can be changed with true
marking that cards will not be blurred by default.
const nsfwDefaultPC = true;
const nsfwDefaultMobile = false;
If you want all cards to be blurred by default and for it to stay that way, you can simply do something like this instead. The .mobile
part can be removed so it works on desktop as well.
<div class="main_image {{Tags}}">{{Picture}}</div>
.mobile .-NSFW img {
filter: blur(30px);
}
.mobile .-NSFW img:hover {
filter: blur(0px);
}
I use the hotkeys in this guide (highly recommended) for adding images/audio to new cards while reading. For the screenshot hotkey, I have a hotkey in addition to the normal one that adds a -NSFW
tag to the new card for convenience so they don't have to be tagged manually after creation. In the argument part of step 8, just use this code instead:
-NoProfile -Command "$medianame = \"%input\" | Split-Path -leaf; $data = Invoke-RestMethod -Uri http://127.0.0.1:8765 -Method Post -ContentType 'application/json; charset=UTF-8' -Body '{\"action\": \"findNotes\", \"version\": 6, \"params\": {\"query\":\"added:1\"}}'; $sortedlist = $data.result | Sort-Object -Descending {[Long]$_}; $noteid = $sortedlist[0]; Invoke-RestMethod -Uri http://127.0.0.1:8765 -Method Post -ContentType 'application/json; charset=UTF-8' -Body \"{`\"action`\": `\"updateNoteFields`\", `\"version`\": 6, `\"params`\": {`\"note`\":{`\"id`\":$noteid, `\"fields`\":{`\"Picture`\":`\"<img src=$medianame>`\"}}}}\"; " Invoke-RestMethod -Uri http://127.0.0.1:8765 -Method Post -ContentType 'application/json; charset=UTF-8' -Body \"{ `\"action`\": `\"addTags`\",`\"version`\": 6,`\"params`\": {`\"notes`\": [$noteid],`\"tags`\": `\"-NSFW`\"}}\";
It's good practice to have your word highlighted within the target sentence so it's easier to see. You can do this for new cards by using the cloze options in Yomichan, but that doesn't affect existing cards that don't have the word highlighted. Here's some code to highlight the target expression within already existing cards. It's quite flexible, being able to work to some degree for most cards even if the sentence doesn't exactly contain the expression, or if it contains the expression but in hiragana or katakana.
To use it, simply append the following script to the end of a card.
{{Expression}}
and {{Reading}}
to match your field.div
with an id of sentence
so the selector is #sentence
as it is by default. For example, <div id="sentence">{{Sentence}}</div>
.<script>
// https://github.com/MarvNC/JP-Resources
(function () {
const expression = '{{Expression}}';
const reading = '{{Reading}}';
const sentenceElement = document.querySelector('#sentence');
highlightWord(sentenceElement, expression, reading);
})();
function highlightWord(sentenceElement, expression, reading) {
const sentence = sentenceElement.innerHTML;
if (!sentence.match(/<(strong|b)>/)) {
let possibleReplaces = [
// shorten kanji expression
shorten(expression, sentence, 1),
// shorten with kana reading
shorten(reading, sentence, 2),
// find katakana
shorten(hiraganaToKatakana(expression), sentence, 2),
// find katakana with kana reading
shorten(hiraganaToKatakana(reading), sentence, 2),
];
// find and use longest one that is a substring of the sentence
replace = possibleReplaces
.filter((str) => str && sentence.includes(str))
.reduce((a, b) => (a.length > b.length ? a : b));
sentenceElement.innerHTML = sentenceElement.innerHTML.replace(
new RegExp(replace, 'g'),
`<strong>${replace}</strong>`
);
}
}
// takes an expression and shortens it until it's in the sentence
function shorten(expression, sentence, minLength) {
while (expression.length > minLength && !sentence.match(expression)) {
expression = expression.substr(0, expression.length - 1);
}
return expression;
}
function hiraganaToKatakana(hiragana) {
return hiragana.replace(/[\u3041-\u3096]/g, function (c) {
return String.fromCharCode(c.charCodeAt(0) + 0x60);
});
}
</script>
Kana-only terms might be annoying to review in Anki as they're quite arbitrary and don't necessarily derive meaning from a kanji. This makes them potentially harder to recall than kanji terms, but not necessarily for much benefit as you'd come across onomatopoeia with context in the while making them somewhat self explanatory as to what they're describing.
Because of this, you might find it helpful to conditionally display the sentence on the front of your cards to be able to learn kana terms along with the context.
Media: 蒼の彼方のフォーリズム EXTRA1 © sprite
In order to conditionally display the sentence on the front, put the following html on the front of your card template where you want your hint sentence.
Replace all instances of {{Sentence}}
with the name of your sentence field, and the same with {{Expression}}
in the code.
The anchor linking to jpdb is completely optional, and is used to make easy searches on jpdb. If you don't want this you can just replace the second line with {{Sentence}}
.
<div id="hintSentence" style="display: none">
<a href="https://jpdb.io/search?q={{Sentence}}">{{Sentence}}</a>
</div>
Put this code at the bottom of your front card template, making sure to rename {{Expression}}
to match your field name.
<script>
// https://github.com/MarvNC/JP-Resources
(function () {
// prevent loading this js on back side of card
if (document.getElementById('answer')) {
return;
}
const expression = '{{Expression}}';
const furigana = '{{Reading}}';
const kanjiRegex = /[\u4e00-\u9faf]/g;
if (!expression.match(kanjiRegex)) {
const hintSentence = document.getElementById('hintSentence');
hintSentence.style.display = 'block';
const sentenceElement = document.querySelector('#hintSentence a');
highlightWord(sentenceElement, expression, furigana);
}
})();
</script>
Some text replacement patterns in Yomichan Settings -> Translation -> Custom Text Replacement Patterns
that I've found useful for better parsing.
If it might save you some time, you can optionally download the text replacement patterns from here, export your config, replace them in the appropriate spot, and reimport. Thanks to Julian for providing the export.
1|1
-> 一
2|2
-> 二
3|3
-> 三
4|4
-> 四
5|5
-> 五
6|6
-> 六
7|7
-> 七
8|8
-> 八
9|9
-> 九
・|、|\-|\.|‐|\s
-> (nothing)
ッ
-> っ
(.)々
-> $1$1
If you're displaying Japanese/Chinese/Korean text in Anki, you might often get incorrect glyphs, as there are differences in the display of unified Han characters for different languages. In general, I recommend setting a lang
tag in your Anki card template so that the card is rendered correctly.
At the beginning of your card template (both front and back sides) add the following line, replacing ja
with zh
, zh-hk
, zh-tw
or ko
as appropriate. You can look up the ISO language code for the language you want to display online.
<span lang="ja">
Then at the very bottom of your card template just add a closing span tag.
</span>
You may already have set a custom font using CSS which is a good way to customize your cards but it does not guarantee full compatibility in cases where the glyph is not present in the font you're using.