このデモの見方
どのボタンを押しても、確かめてほしいのは次の3つです。各ボタンの下に「見どころ」を1行書いてあります。
- 断ったケースを見る。このライブラリの主張は「正しく変換できること」ではなく「確認できないものを変換しないこと」です。宛名ラベルは、断られるより間違っているほうが困ります。プリセットには失敗するものが混ぜてあります——失敗は例外ではなく
{ ok: false, reason }という値で返るので、呼び出し側は必ず分岐することになります - 「このページが送ったリクエスト」を見る。出ているのは都道府県と市区町村までで、番地から先は出ていないことを、URL の一覧そのもので確かめられます
- このデモが配っているのは…市区町村ぶんだけだということ。全国は…市区町村あり、データセットはその1つ1つが別ファイルです。ここに無い市区町村を入れると、ライブラリの答えではなくこのデモの都合で失敗します。そのときはそう表示します(下の「配っている市区町村」に一覧があります)
ライブラリを読み込んでいます…
1. 日本語 → ローマ字toRomaji()
住所を入れると、西洋語順のローマ字表記と、その内訳を返します。全角数字・漢数字・丁目/番/号 とハイフンの揺れ・都道府県の省略は、@geolonia/normalize-japanese-addresses(同梱している版は …)が吸収します。このライブラリが作っているのはその上のローマ字化・語順・出力形式だけです。
2. ローマ字 → 日本語fromRomaji()
逆方向です。外側から内側へ厳密に解決します(都道府県 → 市区町村 → 町名)。あるローマ字表記が実在の複数の町に当たるときは、勝手に1つ選ばず AMBIGUOUS を候補付きで返します——どれなのかを知っているのは、文脈を持っている呼び出し側だからです。
3. このページが送ったリクエスト
ページを開いてからいままでに発生した通信を並べています(PerformanceObserver が見ているので、fetch でも <script> でも画像でも、リクエストを1つ使うものは全部出ます)。上で入力した番地・建物名・宛名がこの一覧に出てこないことが、このライブラリの主張そのものです。出ていたら、それは不具合です。なお入力欄は打ち終わって 0.25 秒で変換します——1文字ごとに変換すると、このデモが配っていない市区町村ではキーストロークのぶんだけリクエストが出て、読むための一覧が埋まってしまうためです。
配っている市区町村
データセットは市区町村ごとに1ファイルで、…都道府県・全国…市区町村ぶんあります。このデモが配っているのは、そのうち下の…件だけです(合計 …)。索引(ja.json、…)は削らずにそのまま配っています——索引を削ると、実在する市区町村をライブラリが「存在しない」と答えることになり、それは欠落ではなく誤答だからです。
4. 受け付ける形と、受け付けない形
このページを開いた時点で実際に実行した結果です。受け付けないほうが多いのは手抜きではありません——住所の変換で怖いのは例外ではなく、それらしい別の住所が自信を持って返ってくることだからです。各ケースには「受けるはず/断るはず」を持たせてあり、食い違ったらこのページが警告を出し、CI が落ちます。デモは npm 公開版を読み込んでいるので、公開済みの版の挙動が変わったときに気づく仕掛けは、これしかありません。
このライブラリが「しない」こと
- 読みを推測しない。ローマ字はすべてデータ由来です——データのローマ字フィールドか、かな読みの決定的な翻字か、そのどちらか。どちらも無ければ
NO_ROMAJI_DATAで失敗します。同梱データでローマ字フィールドを持つのは 89.51%、かなを持つのは 99.55% なので、約1割は翻字経路で出ています(上のプリセット「北海道札幌市中央区円山1-1」がそれです) - 住所正規化を再発明しない。表記ゆれの吸収は
@geolonia/normalize-japanese-addressesに全面的に委譲しています。このパッケージはその上のレイヤーだけです - 京都の通り名をローマ字化しない。通り名は正規化の前に切り離して
parsed.kyotoStreetに原文のまま保持します。データに通り名の読みが無く、読みを推測することこそこのライブラリが拒否していることだからです - 建物名・部屋番号・宛名を翻訳しない。
unparsedとして分離し、手を付けずに素通しします。型にこれらのromajiフィールドが無いのは設計です - ジオコーディングを主張しない。町レベルの座標は同梱データから意図的に落としてあります(約19万レコードぶんのサイズ)
- 郵便番号データを同梱しない。
postalCodeIndexは呼び出し側が自前データを差し込むフックで、日本郵便のKEN_ALLは持ちません - ホスト型 API を用意しない。ブラウザでエンドポイントを指定しなければ
DATA_NOT_CONFIGUREDで失敗します。フォールバック先を持たないのは設計で、持った瞬間に「住所を外に出さない」が嘘になるからです - 正しさを保証しない。MIT ライセンスの "AS IS" 提供です。このライブラリが保証しているのは「確認できないものを変換しないこと」であって、「答えが正しいこと」ではありません
使う
npm install jp-address-romaji@0.1.7 jp-address-romaji-data@0.1.5
import { toRomaji, fromRomaji } from 'jp-address-romaji';
await toRomaji('東京都新宿区西新宿二丁目8番1号');
// → { ok: true, value: { formatted: '2-8-1 Nishishinjuku, Shinjuku-ku, Tokyo, Japan', … } }
await fromRomaji('2-8-1 Nishishinjuku, Shinjuku-ku, Tokyo');
// → { ok: true, value: { formatted: '東京都新宿区西新宿二丁目8-1', … } }
Node ではこれだけで動きます。データはローカルのファイルから読み、変換時にネットワークへ出ません。このページと同じことをブラウザでやるなら、データを自分で配信してその場所を指定します:
import { configureDataSource, toRomaji } from 'jp-address-romaji';
configureDataSource({ endpoint: 'https://your-site.example/address-data/ja' });
ライブラリが読むのは <endpoint>.json(都道府県・市区町村の索引)と、必要な1市区町村ぶんの <endpoint>/<都道府県>/<市区町村>.json だけなので、必要な市区町村だけを配信することもできます——このページがまさにそれです。ESM 専用・Node 18 以上。configureDataSource({ dataDir }) はブラウザでは動作せず、DATA_NOT_CONFIGURED になります(「近い挙動」に倒さないため)。