Kristopher Baker iOSを土台に · プロダクトシステム · AI支援ワークフロー
← Aoede

shipped · 2026.06.07 · 約2分

音声と一致するふりがな

Aoedeで漢字の上に小さな読み仮名、つまりふりがなを表示できるようになりました。日本語のときだけ出るツールバーのボタンで切り替えます。こだわったのは、ふりがなが音声と一致することです。表示される読みも、読み上げられる読みも、どちらもOpenJTalkから来ます。だからナレーターが「私」を「わたし」と読むとき、漢字の上に見えるのもまさにそれで、文脈で決まる助詞の読みまで一致します。OpenJTalkの辞書がなければ、ふりがなは音声と同じくCFStringTokenizerにフォールバックします。

姉妹アプリのAsideがすでにふりがなをやっているので、まずはそのロジックに手を伸ばしました。読みのコードはきれいに移植できました。トークン化し、ひらがなに変換し、送り仮名を落とし、混じった漢字の連なりを分割する。でも描画はそうはいきませんでした。AsideはルビをひとつのCTRubyAnnotationで、一枚岩のテキストブロックに描きます。一方、Aoedeの読書体験の核は、そのテキストの上を単語ごとに滑っていくカラオケ式のハイライトです。一枚岩のブロックには、ハイライトが乗る場所がありません。そこで描画をSwiftUIで単語ごとに作り直しました。漢字の連なりごとに上へ仮名を重ね、ふつうの文字の上には透明な仮名レーンを置いて、どの行もベースラインをそろえます。ハイライトは生き残り、いまはふりがなを突き抜けるのではなく、その下を滑っていきます。

小さなバグひとつが、寄り道する価値のあるものでした。漢字の連なりが読みとほぼ同じ幅のとき(「物凄」は「ものすご」とだいたい同じ幅です)、仮名で測った列がほんのわずか足りず、SwiftUIが漢字そのものを「…」一文字に切り詰めてしまうことがありました。仮名レーンだけでなく、ベースの文字列も自前の理想幅に固定して直しました。ふりがなは紙の上では小さな機能ですが、まだ勉強中の言語で読むとき、聞いている読みが目に見えることは、ほとんどそれ自体が目的です。