Search that finds nothing in Japanese
Japanese is written without spaces, and most search indexes find words by the spaces and punctuation between them. Your search box then finds a Japanese note only when the query is the whole sentence up to the next comma. Split the text into words before you index it, and split the query the same way:
const seg = new Intl.Segmenter(
"ja", { granularity: "word" });
function words(text) {
return [...seg.segment(
text.normalize("NFKC"))]
.filter((s) => s.isWordLike)
.map((s) => s.segment)
.join(" ");
}
words("日本語の全文検索は難しい") returns "日本語 の 全文 検索 は 難しい" in Node.js 24. Intl.Segmenter is built into JavaScript; it splits Japanese with a dictionary, so the words are not always the ones a person would pick (請求書, "invoice", comes out as 請求 書), but it splits the query the same way, and that is what matters. normalize("NFKC") makes PDF and PDF the same word (why).
In SQLite, keep the split text in the column you index, and search for the split query as a phrase:
create virtual table notes_fts using fts5(body_words);
insert.run(words(body)); const q = '"' + words(query) + '"'; const rows = db.prepare( "select rowid from notes_fts " + "where notes_fts match ?").all(q);
What SQLite's FTS5 finds
We indexed four short Japanese notes in SQLite 3.53 (Node.js 24's node:sqlite) and searched for words inside them. Rows found:
| Query | default | trigram | words() |
|---|---|---|---|
| 請求書 | 0 | 2 | 2 |
| 検索 | 0 | 0 | 3 |
| 住所 | 0 | 0 | 1 |
PDF | 0 | 0 | 1 |
FTS5's default tokenizer, unicode61, treats letters as part of a word, and kanji and kana are letters: "Each contiguous run of one or more token characters is considered to be a token" (SQLite's docs). A Japanese sentence up to the next punctuation mark is one word, and only the whole sentence finds it.
The trigram tokenizer matches any substring, but "Substrings consisting of fewer than 3 unicode characters do not match any rows" (the same docs), and many Japanese words have two characters: 検索 ("search"), 住所 ("address"). LIKE '%検索%' on the trigram table does find them, by reading every row: on 200,000 rows it took 84 ms, where a three-character LIKE took 0.3 ms. Neither tokenizer makes the full-width PDF that a Japanese input method types match PDF.
The same bug, in real apps: orca #28256, open since October 2026, where session search misses Chinese and Japanese words inside longer text because unicode61 indexes the whole run; a pull request with a trigram fix isn't merged yet. And emdash #2245, where search silently returned nothing for languages written without spaces, Japanese among them; the fix, merged in August 2026, made the tokenizer configurable.
PostgreSQL and Supabase
Supabase's docs say native Postgres full text indexing "is limited to alphabet and digit based languages", and point to PGroonga, an extension Supabase offers, for Japanese and Chinese (its page on PGroonga):
create index memos_content on memos using pgroonga (content); select * from memos where content &@~ '検索';
That is Supabase's example with a Japanese query; we have not run PostgreSQL for this page. The trigram extension, pg_trgm, has the same limit as SQLite's trigram for two-character words: "a pattern with no extractable trigrams will degenerate to a full-index scan" (its docs).
Meilisearch
Meilisearch splits Japanese with a dictionary (Lindera, with the IPA dictionary), once it knows the text is Japanese. It detects the language by itself, and its guide to multilingual data warns that Chinese and Japanese are "very difficult" to tell apart automatically, and that short queries are harder to identify. Declare the language for your Japanese fields and for each search:
// index settings
{ "localizedAttributes": [
{ "locales": ["jpn"],
"attributePatterns": ["*_ja"] }
] }
// each search
{ "q": "検索", "locales": ["jpn"] }
These follow Meilisearch's docs; we did not run Meilisearch.
Readings are another index
None of these finds 検索 when someone types けんさく, its reading in hiragana; in our test, every index above found nothing for it. Kanji have no reading in the text. If people search names or products by how they sound, store the reading in its own field, typed in when the record is made, and search that too.
The rest of a Japanese check
A search box that finds nothing looks like an empty app. The same pass catches Enter while typing Japanese (the fix), yen charged 100 times over (the fix), kanji drawn in their Chinese shapes (the fix), headings that break in the middle of a word (the fix), postal codes rejected when typed in Japanese (the fix), dates saved one day early in Japan (the fix), address forms in the American order (the fix), phone numbers sent to +81 with the 0 still in (the fix), PDFs with the Japanese missing (the fix), previews cut down to “...” in Japanese (the fix), lists sorted in the wrong order (the fix), email subjects that arrive garbled (the fix), CSV files that open garbled in Excel (the fix), Japanese titles that give an empty URL slug (the fix), file names garbled on upload and download (the fix), dates in the Japanese era that come out wrong (the fix), full-width spaces that get past your checks (the fix), public holidays your app gets wrong (the fix), and vertical text that comes out sideways or upside down (the fix).
Lesstep translates web apps into Japanese and delivers them as one pull request. In Complete (US$249), we check every screen in Japanese, the search box included, and tell you what it misses. The first step is a free sample.
SQLite is a registered trademark of Hipp, Wyrick & Company, Inc.; PostgreSQL is a registered trademark of the PostgreSQL Community Association; Supabase is a trademark of Supabase, Inc.; Meilisearch is a trademark of Meili SAS; Node.js is a trademark of the OpenJS Foundation. This page is not affiliated with or endorsed by any of them.
More: Enter sends the message while typing Japanese · Stripe charges 100 times too much in yen · Kanji in their Chinese shapes · Japanese headings that break in the middle of a word · Forms that reject numbers typed in Japanese · Dates that come out wrong for Japanese users · Address forms in the Japanese order · Japanese phone numbers in forms · Japanese text missing from your PDFs · Length limits that break in Japanese · Japanese lists sorted in the wrong order · Japanese email subjects that arrive garbled · Japanese CSV files that open garbled in Excel · Japanese titles that give an empty URL slug · Japanese file names garbled on upload and download · Japanese era dates that come out wrong · Full-width spaces that get past your checks · Japanese public holidays your app gets wrong · Japanese vertical text that comes out sideways or upside down · Japanese localization checklist · Japanese localization for your web app