Why Your Chat Box Sends Half a Japanese Sentence

If your chat box sends the message when someone presses Enter, it will send half finished Japanese. Japanese, Chinese and Korean users type through an input method editor, and they press Enter to confirm the conversion of a word, not to send. The fix is to ignore Enter while a composition is active: check event.isComposing, and also keyCode === 229 for Safari.

I live in Tokyo and type in four languages on most days. This is the bug I hit most often in AI products built outside Asia, including some very well funded ones. You type a few words in hiragana, press Enter to turn them into kanji, and the message is gone, with the wrong characters in it, while the model is already answering a question you did not finish asking.

What an IME does with the Enter key

Typing Japanese on a laptop is a two step process. You type sounds on a Latin keyboard, the input method shows them as hiragana with an underline, you press Space to cycle through kanji candidates, and you press Enter to commit the one you want. Only after that commit is the text really in the field.

That underlined stage is called a composition. The browser marks it with a compositionstart event when it begins and compositionend when the text is committed. During a composition, Enter belongs to the input method. A sentence of normal length can contain five or six of those Enter presses before the person is ready to send anything.

Chat interfaces made this worse. Ten years ago most forms needed a click on a submit button. AI products copied the messaging app pattern where Enter sends and Shift plus Enter adds a new line, and a lot of those handlers were written and tested only in English.

The fix in code

MDN documents the pattern directly on the keydown event page. Check isComposing, and check keyCode for the value 229, which browsers set on key events that the input method has processed:

textarea.addEventListener("keydown", (event) => {
  if (event.isComposing || event.keyCode === 229) return
  if (event.key === "Enter" && !event.shiftKey) {
    event.preventDefault()
    send()
  }
})

You need the second check. MDN notes that compositionend can fire before the keydown of the key that closes the input method, so isComposing is false on exactly the Enter press you care about. keyCode is deprecated, but it is still 229 in that case.

Why Safari needs the extra check

The browser compatibility data behind MDN lists Safari's support for isComposing as partial. Its note says that for the keystroke that completes a composition, the keydown and input events are dispatched after compositionend instead of before, so isComposing is false when you would expect true. Chrome and Firefox behave as expected.

That matters on the Mac, and on iPhone and iPad, where Safari and most other browsers still run on WebKit. A team that tests on Chrome on a Windows laptop with a Japanese input method will see the first check work and ship. A Japanese user on a MacBook in Safari gets the bug anyway.

If you use a framework, check what it does for you. Some UI libraries handle this inside their text input components and some leave it to you. React passes the native event through as event.nativeEvent, so the same two checks work there.

Test it like a Japanese user would

You do not need to read Japanese to test this. Add the Japanese input method on your Mac or PC, switch to it, type konnichiha in your chat box, press Space to convert, then press Enter once. Nothing should send. Press Enter a second time and the message should go.

Do the same in Safari, in Chrome, and on an iPhone with the Japanese keyboard. On the phone, also try the Chinese pinyin keyboard; Chinese input has the same composition step and the same failure.

Two more cases are worth a minute. Paste a Japanese sentence and press Enter, which should send because no composition is active. And try the send button with an unconfirmed composition still underlined, then decide on purpose whether that commits the text or waits.

The bigger lesson for AI products

Large language models are good at Japanese now. That has made it easy to assume a product works in Japan because the answers come back in fluent Japanese. The input box is where it breaks, and it breaks before the model is ever involved.

This connects to something I keep writing about: Japanese users judge a product by how carefully it handles small things, and a broken Enter key reads as a product that was not made for them. I covered the wider pattern in what makes Japanese UX different, and why the written interface carries so much weight in the piece on Japan's English writing scores. The IME check is four lines of code, and for a Japanese user it is often the first sign that someone tested the product in their language.

← All posts