# ひらがなを受け付けず、理由も示さないフリガナ欄

Source: https://easeweb.dev/learn/furigana-fields
Topics: フォーム > 入力欄が全角と半角のどちらも受け付ける (WCAG 3.3.1, 3.3.3)
The fix: 読みを確認する前に変換し、ひらがなや半角カタカナを全角カタカナにして、同じ読みとして送信します。どうしても全角カタカナしか受け付けられない欄では、読みを「正しくない」と言うだけのメッセージをやめ、ラベルのそばとメッセージで全角カタカナで入力するよう伝えます。入力中の読みを削除したり書き換えたりすることは、どちらの場合もしません。
Test with: input method, keyboard, screen reader
References: https://www.w3.org/WAI/WCAG22/Understanding/error-suggestion.html https://www.w3.org/WAI/WCAG22/Understanding/error-identification.html https://www.w3.org/WAI/WCAG22/Techniques/general/G85 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize https://www.unicode.org/charts/PDF/U3040.pdf https://www.php.net/manual/en/function.mb-convert-kana.php https://developer.chrome.com/blog/japanese-phonetic-name-autofill https://www.digitalservice.metro.tokyo.lg.jp/documents/d/digitalservice/inputform_guidance_v11

よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。

## 場面

ショップの購入手続きで、名前に続いて、その読みをフリガナとして「セイ」と「メイ」の2つの欄に入力します。Alex Morganさんは、直前まで住所を入力していたので、日本語入力をオンにしたまま読みを入力します。mo-gannと打つと「もーがん」と表示されます。IMEは、変換しない限りひらがなで入力します。カタカナにするには、確定の前に変換するひと手間が要りますが、「もーがん」のままでも読みとしては正しく見えるので、変換せずに確定しても不思議はありません。「もーがん」と「モーガン」は、同じ読みを2種類のかなで書いたものです。

この欄の確認は、全角カタカナの「ァ」から「ヶ」までと、長音符「ー」しか想定していません。「もーがん」は「フリガナを正しく入力してください。」とはじかれます。読みを見返しても音はどれも合っているので、そのまま送り直しますが、同じメッセージが出ます。読みは正しく、文字の種類だけが違うことは、どこにも書かれていません。ほかからコピーした半角カタカナの「ﾓｰｶﾞﾝ」も、同じようにはじかれます。

## 確認できる問題

読みそのものに誤りはありません。欄が、どの文字で入力するかを伝えないまま値をはじいているので、問題は、そのときページが何を伝えるかにあります。

達成基準3.3.3「エラー修正の提案」は、入力エラーを検出し、修正方法が分かっている場合は、それを提案することを求めています。ページが求めているのは全角カタカナだと、はっきりしています。確認で調べているのは、まさにそこだからです。それなのに「フリガナを正しく入力してください」は、そのことを伝えていません。達成方法G85は、入力が求める形式から外れたときに、何が求められているかをテキストで説明する方法です。この達成基準の解説書は、誰のための基準かも挙げています。認知に障害があり、エラーの直し方を理解しにくい人と、視覚に障害があり、直し方を正確に把握できないことがある人です。音はすべて合っていて、文字の種類だけが違うという直し方は、どちらの人にも推測できません。

この例が満たしていないのは、達成基準3.3.1「エラーの特定」ではありません。フリガナが正しくないことはメッセージがテキストで伝えており、はじかれた欄には、コードでそれぞれ無効の状態を設定しています。受け付けない文字を入力したそばから削除する欄は、3.3.1も満たしません。その例は、電話番号欄を題材にした「[全角数字を受け付けず、理由も示さない入力欄](/ja/learn/full-width-digits)」で扱っています。

## 利用者への影響

日本語で入力する人なら、能力にかかわらず、この問題に出会うことがあります。IMEは変換するまでひらがなで入力し、ブラウザーの自動入力が読みをひらがなで入れることもあります。下に挙げるのは、特に負担が大きい人です。

## 自動チェックとAIの限界

欄にはラベルがあり、メッセージもテキストで示されるため、マークアップに誤りはなく、スキャンも通ります。スキャンは文字を入力せず、欄がカタカナを求めていると知っているテスト担当者はカタカナで入力するため、確認はいつも通ってしまいます。AIアシスタントに「カタカナだけを受け付けるフリガナ欄」を頼むと、下の修正前のようなコードが返ってくることがあります。EaseWebの診断は、ページの日本語の部分で、欄自身のラベルに「フリガナ」「ふりがな」「カナ」「kana」とある欄を、人が試す項目として挙げます。ひらがな、全角カタカナ、半角カタカナで入力して確かめてもらうためです。ただし、下の修正前のように「フリガナ」の見出しの下で「セイ」「メイ」とだけラベルを付けた欄は、まだ挙げられません。また、診断はフォームを送信しないため、読みがはじかれたときにページが何を伝えるかまでは分かりません。

## 修正前：読みが正しくないとだけ伝える確認

```html
<form>
  <fieldset>
    <legend>フリガナ</legend>
    <label for="kana-family">セイ</label>
    <input id="kana-family" name="kana-family" aria-describedby="kana-error">
    <label for="kana-given">メイ</label>
    <input id="kana-given" name="kana-given" aria-describedby="kana-error">
  </fieldset>
  <p id="kana-error"></p>
  <button type="submit">次へ</button>
</form>
```

```js
const form = document.querySelector('form');
const fields = form.querySelectorAll('input');
const error = document.getElementById('kana-error');

form.addEventListener('submit', (event) => {
  let valid = true;
  for (const field of fields) {
    const ok = /^[ァ-ヶー]+$/.test(field.value);
    field.setAttribute('aria-invalid', String(!ok));
    if (!ok) valid = false;
  }
  error.textContent = valid ? '' : 'フリガナを正しく入力してください。';
  if (!valid) event.preventDefault();
});
```

- 確認は全角カタカナしか受け付けないため、ひらがなの「もーがん」も、半角カタカナの「ﾓｰｶﾞﾝ」も通りません。
- メッセージはフリガナが正しくないと言うだけで、カタカナなら通ることを伝えていません。

## 修正後：ひらがなと半角カタカナを変換してから確認する

```html
<form>
  <fieldset>
    <legend>フリガナ</legend>
    <label for="kana-family">セイ</label>
    <input id="kana-family" name="kana-family" aria-describedby="kana-error">
    <label for="kana-given">メイ</label>
    <input id="kana-given" name="kana-given" aria-describedby="kana-error">
  </fieldset>
  <p id="kana-error"></p>
  <button type="submit">次へ</button>
</form>
```

```js
const form = document.querySelector('form');
const fields = form.querySelectorAll('input');
const error = document.getElementById('kana-error');

// 半角カタカナとひらがなを全角カタカナにする。
function toKatakana(value) {
  return value
    .normalize('NFKC')
    .replace(/[ぁ-ゖ]/g, (kana) => String.fromCharCode(kana.charCodeAt(0) + 0x60))
    .trim();
}

form.addEventListener('submit', (event) => {
  let valid = true;
  for (const field of fields) {
    const kana = toKatakana(field.value);
    const ok = /^[ァ-ヶー]+$/.test(kana);
    field.setAttribute('aria-invalid', String(!ok));
    if (ok) field.value = kana;
    else valid = false;
  }
  error.textContent = valid ? '' : 'フリガナはひらがなかカタカナで入力してください。例：モーガン';
  if (!valid) event.preventDefault();
});
```

1. Unicodeの互換正規化 `normalize('NFKC')` で値を変換します。半角カタカナが全角になり、半角の「ﾞ」「ﾟ」は前の文字とまとまって1文字になるので、「ﾓｰｶﾞﾝ」は「モーガン」になります。
2. 続く置換で、ひらがなをカタカナにします。Unicodeでは、「ぁ」から「ゖ」までのひらがなに対応するカタカナが、それぞれコードポイントで0x60後ろにあるため、「もーがん」は「モーガン」になります。長音符「ー」は、ひらがなでもカタカナでも同じ文字です。
3. 読みの前後に入力されたスペースを取り除きます。
4. その後で読みを確認します。ひらがなでも、カタカナでも、半角カタカナでも通ります。
5. 各欄には変換した読みを入れます。フォームはその読みを送信します。
6. アルファベットで入力した読みのように、それでもはじかれる値には、何を入力すればよいかを、例と一緒にメッセージで伝えます。

これで修正前の例は直り、3.3.3を満たします。リクエストはこのスクリプトを通らずにサーバーに届くこともあるため、サーバーでも同じように変換してください。

## 修正後：どのカナで入力するかを伝える

```html
<form>
  <fieldset>
    <legend>フリガナ（全角カタカナ）</legend>
    <label for="kana-family">セイ</label>
    <input id="kana-family" name="kana-family" aria-describedby="kana-error">
    <label for="kana-given">メイ</label>
    <input id="kana-given" name="kana-given" aria-describedby="kana-error">
  </fieldset>
  <p id="kana-error"></p>
  <button type="submit">次へ</button>
</form>
```

```js
const form = document.querySelector('form');
const fields = form.querySelectorAll('input');
const error = document.getElementById('kana-error');

form.addEventListener('submit', (event) => {
  let valid = true;
  for (const field of fields) {
    const ok = /^[ァ-ヶー]+$/.test(field.value);
    field.setAttribute('aria-invalid', String(!ok));
    if (!ok) valid = false;
  }
  error.textContent = valid ? '' : 'フリガナは全角カタカナで入力してください。例：モーガン';
  if (!valid) event.preventDefault();
});
```

1. 確認はそのままにします。
2. 欄のグループの見出し（`legend`）に「フリガナ（全角カタカナ）」と書きます。利用者は最初から全角カタカナで入力できます。
3. メッセージにも、例と一緒にカナの種類を書きます。ひらがなで入力した人にも、何を直せばよいかが分かります。

3.3.3は満たしますが、読みははじかれたままで、ひらがなで入力した人は、カタカナに変換して送り直す必要があります。

## どの方法を選ぶか

どちらも3.3.3を満たします。使うべきなのは、読みを変換する方法です。読みはもともと正しく、変換は短い関数1つで済み、2つ目の方法で利用者に入力してもらうのと同じ全角カタカナが保存されます。どのカナで入力するかを伝える方法は、ラベルとメッセージしか編集できないフォームサービスのように、入力チェックを変えられない場合に使います。ただし、ひらがなで入力した人は全員、変換して送り直すことになります。

## 実装の判断

変換は、フォームを送信するときか、欄からフォーカスが外れたときに行い、`input` のハンドラーでは行いません。IMEで変換している間、入力中の文字はIMEが扱っています。その間に値を書き換えると、利用者の入力を妨げます。変換中にブラウザーが送るイベントと、それを `event.isComposing` で見分ける方法は、「[IMEの変換確定のEnterで送信される入力欄](/ja/learn/ime-composition)」で扱っています。

`pattern="[ァ-ヶー]+"` のように、ブラウザー自身に確認させる `pattern` が欄にある場合、ブラウザーは送信時のハンドラーが変換する前の、入力されたままの値を調べます。そのときChromeが出すメッセージは「指定されている形式で入力してください。」だけで、欄に `title` があれば、その内容が添えられます。`pattern` は付けずに、送信時のハンドラーで変換してから確認するか、`pattern` でひらがなと半角カタカナも受け付けて、サーバーで変換します。

読みはブラウザーも入力します。Chromeの自動入力は、欄のラベルにカタカナが1文字でもあれば、保存した読みをカタカナで入力し、なければひらがなで入力します。「ふりがな」や英語のラベルの欄には、ひらがなが入ります。変換していれば、どちらでも受け付けられます。

サーバーでは、PHPの `mb_convert_kana($kana, 'KVC')` で同じ変換ができます。`K` が半角カタカナを全角に、`V` が濁点と半濁点を前の文字とまとめ、`C` がひらがなをカタカナにします。ほかの言語では、NFKCの後に、同じく0x60ずらす変換をします。

`[ァ-ヶー]` は「ヴ」や、「ッ」「ャ」などの小さい文字も受け付けます。読み全体を1つの欄で受け取る場合は、姓と名の間のスペースも必要です。外国の名前の読みは、間に中黒「・」や「＝」を入れて書くことも多いため、こうした区切りの文字も受け付けてください。後の処理でカタカナが必要でなければ、カタカナにこだわる必要もありません。GovTech東京の「入力フォーム ガイダンス」は、フリガナ欄で漢字、ひらがな、カタカナ、英字を、全角でも半角でも受け付けるとしています。

## 修正の確認

1. 日本語入力をオンにし、読みをひらがなで入力して、変換せずにEnterで確定し、フォームを送信する。受け付けられてカタカナで送信されるか、全角カタカナで入力するようメッセージで伝えられる。
2. 「ﾓｰｶﾞﾝ」のような半角カタカナの読みを貼り付けて、フォームを送信する。結果は手順1と同じになる。
3. ブラウザーの自動入力で欄を埋めて、フォームを送信する。結果は手順1と同じになる。
4. 「Morgan」のようにアルファベットで読みを入力して、フォームを送信する。何を入力すればよいかが、例と一緒にメッセージで伝えられる。
5. スクリプトを無効にするか、テスト用のリクエストで、ページのスクリプトを通さずにひらがなの読みをサーバーへ送る。サーバーが変換するか、カナの種類を明記したメッセージではじく。
6. スクリーンリーダーを起動し、ひらがなの読みを送信する。欄にフォーカスすると、メッセージが一緒に読み上げられ、何を直せばよいかが分かる。

OS、ブラウザー、IME、支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。共通のフォームの欄やその入力チェックを変更した際は、再度確認します。

## 制限

このサンプルは、どのアプリケーションでも同じ結果になることを保証するものではありません。この例では、読みを2つの欄で受け取り、全角カタカナで保存しています。読みをひらがなや半角カタカナで保存するシステムでは、逆向きの変換が必要です。変換が変えるのは文字の種類だけで、読みが名前と合っているかまでは分かりません。アルファベットで入力した読みには、メッセージが出ます。電話番号や郵便番号の欄で全角数字をはじくのも同じ問題で、「[全角数字を受け付けず、理由も示さない入力欄](/ja/learn/full-width-digits)」で扱っています。送信に失敗した後、フォーカスの移動やエラーの一覧でメッセージをどう届けるかは、「[直し方がわからないフォームエラー](/ja/learn/accessible-form-errors)」で扱っています。

---

このガイドをコーディングエージェントで使う: MCP https://easeweb.dev/mcp（設定は https://easeweb.dev/ja/services/developers）
