npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

menpai

v0.1.0

Published

Translate Taiwan (zh-TW) postal addresses into the Chunghwa Post / UPU English format. Zero dependencies, offline, typed, with per-segment confidence.

Readme

menpai

門牌 ménpái — the address plate on a Taiwanese house. menpai rewrites that address in the English format used by Chunghwa Post and the UPU.

import { translate } from "menpai";

translate("台北市大安區忠孝東路四段1號3樓之2").english;
// → "3 F.-2, No. 1, Sec. 4, Zhongxiao E. Rd., Da'an Dist., Taipei City 106, Taiwan (R.O.C.)"

translate("106070 臺北市大安區忠孝東路四段216巷27弄1-1號3樓之2, 5室").english;
// → "Rm. 5, 3 F.-2, No. 1-1, Aly. 27, Ln. 216, Sec. 4, Zhongxiao E. Rd., Da'an Dist., Taipei City 106070, Taiwan (R.O.C.)"

translate("高雄市三民區民族一路100號", { romanization: "tongyong" }).english;
// → "No. 100, Minzu 1st Rd., Sanmin Dist., Kaohsiung City 807, Taiwan (R.O.C.)"

zero dependencies · 138 kB gzipped (ESM bundle, all data included) · offline · ESM + CJS · TypeScript

Every result says how sure it is:

const r = translate("台北市信義區不存在的路99號");
r.english;     // "No. 99, Bucunzaide Rd., Xinyi Dist., Taipei City 110, Taiwan (R.O.C.)"
r.confidence;  // "inferred"  — the road is not in the official list; its pinyin is a guess
r.unresolved;  // ["不存在的路"]
r.segments;    // [{ key: "number", value: "No. 99", confidence: "exact" },
               //  { key: "road", value: "Bucunzaide Rd.", confidence: "inferred" }, ...]

A wrong address gets a parcel lost. This library would rather tell you "I am not sure" than pretend.

Install

npm install menpai

Node ≥ 18, browsers, and edge runtimes. Pure functions, no I/O, no side effects at import time.

API

Three functions. Nothing else is exported besides their types.

translate(input, options?) → FormatResult

parse followed by format. If the input cannot be parsed, english is "", confidence is "unknown", and unresolved holds the whole input. If part of the input could not be interpreted (a building name, a note), it is appended to unresolved and confidence drops to "unknown" — a confident answer is never returned for text that was ignored.

parse(input) → ParseResult

Chinese address → structured parts.

const p = parse("桃園縣中壢市中央西路二段30號");
// {
//   ok: true,
//   parts: { city: "桃園市", area: "中壢區", road: "中央西路", section: "2", number: "30" },
//   unparsed: "",
//   warnings: [
//     { code: "city-alias", message: '"桃園縣" was read as "桃園市".' },
//     { code: "area-alias", message: '"中壢市" was read as "中壢區".' }
//   ]
// }

Accepted input variations: / , full-width digits, Chinese numerals (四段, 十二樓, 二百一十六巷), 3F / 3F-2 for 3樓之2, 1-1號 / 1之1號 / 1號之1, 3 / 3+2 / 3+3 postal codes with or without a hyphen, whitespace and commas anywhere, pre-2010/2014 county and township names (臺北縣板橋市新北市板橋區), a missing city when the district name is unique in Taiwan, and a district that exists in several cities when the postal code settles it.

ok: false is returned only when no city can be determined:

| error.code | Meaning | | --- | --- | | empty-input | Nothing to parse. | | city-not-found | No city / county at the start, and no unique district either. | | area-ambiguous | e.g. 大安區… alone — exists in 臺北市 and 臺中市; add the city or a postal code. |

warnings[].code: city-alias, area-alias, city-inferred-from-area, postal-code-mismatch (the code in the input does not belong to that district; it is kept, not corrected), unparsed-remainder.

format(parts, options?) → FormatResult

Structured parts → English. Use it directly when the address already lives in separate fields.

format({ city: "新北市", area: "板橋區", road: "文化路", section: "1", number: "188", floor: "12" }).english;
// → "12 F., No. 188, Sec. 1, Wenhua Rd., Banqiao Dist., New Taipei City 220, Taiwan (R.O.C.)"

Types

interface AddressParts {
  postalCode?: string;   // "106" | "10607" | "106070"
  city?: string;         // 臺北市
  area?: string;         // 大安區 / 民雄鄉 / 竹北市
  village?: string;      // 豊收村 / 龍門里
  neighborhood?: string; // 鄰 number
  road?: string;         // 忠孝東路 (路 / 街 / 大道, or a place name)
  section?: string;      // 段 number (or a named section)
  lane?: string;         // 巷 number (or a named lane)
  alley?: string;        // 弄
  subAlley?: string;     // 衖
  number?: string;       // 號
  numberSuffix?: string; // 附號: the 1 in 1之1號
  floor?: string;        // 樓
  floorSuffix?: string;  // the 2 in 3樓之2
  room?: string;         // 室
}

interface FormatOptions {
  romanization?: "hanyu" | "tongyong" | "wade-giles"; // default "hanyu"
  postalCode?: 3 | 5 | 6;  // digits to emit; default: as many as are known
  country?: boolean;       // append ", Taiwan (R.O.C.)"; default true
}

type Confidence = "exact" | "inferred" | "unknown";

interface FormatResult {
  english: string;
  confidence: Confidence;  // the lowest confidence of all segments
  segments: Array<{ key: keyof AddressParts; value: string; confidence: Confidence }>;
  unresolved: string[];    // Chinese fragments rendered by a fallback (or left as-is)
}

Confidence

| Level | Meaning | | --- | --- | | exact | The name is in the official Chunghwa Post list, or the segment is a structural token (No., Sec., F.) whose form is fixed by the Chunghwa Post writing guideline. | | inferred | Produced by a fallback: character-by-character pinyin plus suffix rules (Rd., trailing E., 一路1st Rd.). Also every Wade-Giles conversion, since no official reference exists for it. The Chinese fragment is listed in unresolved. | | unknown | Could not be translated (a character with no reading, a postal code that contradicts the district, text that was not understood). The value is passed through so a human can see it. |

The overall confidence is the minimum over segments.

Output format

Follows the order and abbreviations of the Chunghwa Post writing guideline, small to large:

Rm. 室 → F. 樓 (3 F.-2 for 3樓之2) → No. 號 (No. 1-1 for 1之1號) → Sub-Alley 衖 → Aly. 弄 → Ln. 巷 → Sec. 段 → road (Rd. 路, St. 街, Blvd. 大道; E. / W. / S. / N.; 1st / 2nd …) → Neighborhood 鄰 → Vil. 村/里 → Dist. 區 / Township 鄉·鎮 / City 縣轄市 → city or county + postal code → Taiwan (R.O.C.).

Conventional spellings are used where Chunghwa Post uses them: Taipei, New Taipei, Kaohsiung, Keelung, Hsinchu, Taichung, Chiayi, Pingtung, Kinmen, Hualien, Taitung, Lienchiang, Tamsui Dist., Lukang Township, East Dist., Roosevelt Rd., Civic Blvd., Keelung Rd.. Multi-reading characters follow the official list, not a generic pinyin algorithm: 重慶北路 is Chongqing N. Rd., 廈門街 is Xiamen St..

Romanization applies to names that are not conventional: hanyu (default, the official system), tongyong (Jhongsiao, Banciao), wade-giles in the simplified Taiwan form without aspiration marks, diaereses or hyphens (Chunghsiao, Hsinyi).

Verification

  • Official data replay — every one of the 30,030 road rows, 8,369 village / named-lane rows and 371 district rows of the vendored Chunghwa Post files is pushed through format() and must come back byte-for-byte (test/data.test.ts). The fallback rules are pinned to the official spellings.
  • Property-based — random combinations of real districts, roads, villages and numbers are written out in random spellings (臺/台, Chinese / full-width numerals, 3F, 1-1號, stray spaces and commas), parsed back, and must format identically (fast-check, test/roundtrip.property.test.ts).
  • Golden cases against the official web tooltest/fixtures/golden.json holds 120 addresses (every city, multi-reading roads, sections, lanes, alleys, floors, suffixes, same-named districts, Tongyong). Their expected values are filled in by hand from the Chunghwa Post translation tool; cases still marked null are reported as todo and assert nothing. Status: pending — no golden case has been verified yet. This README will state the pass count once they are.

Non-goals

  • Address existence validation. 臺北市大安區忠孝東路四段99999號 translates fine; whether the house exists is not this library's business.
  • Postal code lookup or reverse lookup. 3-digit codes come with the district; 3+2 / 3+3 codes are only passed through from the input.
  • English → Chinese.
  • Calling the Chunghwa Post website at runtime. Everything is offline.
  • Configuration files, plugins, custom dictionaries.
  • Addresses outside Taiwan.

Data

All names come from files published by Chunghwa Post (中華郵政) on its download page: the road list (edition 113/01, 2024-04-01), the village and named-lane list (113/01), and the city / district list with postal codes (109/06). The vendored copies, URLs and checksums are in data/source/; the reasoning behind the data layout is in docs/data-notes.md. npm run build:data regenerates src/data/ and CI fails if the committed output drifts.

donma/TaiwanAddressCityAreaRoadChineseEnglishJSON (MIT) was the starting point of this project; its data turned out to be from 2016, so the current official files are used instead. See NOTICE.

License

MIT © Sean Chou. Data © Chunghwa Post Co., Ltd.; see NOTICE.