Back to blog
laravel internationalization

Is your international address form getting Japan wrong?

November 11, 2026

We've seen address forms implementing "international support" as a country dropdown and a few text fields, one of them generically labelled "State/Province". The form fields are the same regardless of which country you pick.

That works fine for addresses that follow one specific model — street number + street name, city, state, postal code. It falls apart immediately for Japan.

How Japanese addresses actually work

Western addresses move from specific to general: street number → street → city → state → country. Japanese addresses move from general to specific — the opposite direction entirely:

〒150-0002
東京都          ← Prefecture (Tokyo Metropolis)
渋谷区          ← Ward (Shibuya)
渋谷            ← Neighborhood (Shibuya)
2丁目           ← Chōme (district 2)
21番地          ← Ban (block 21)
1号             ← Gō (building 1)
渋谷ヒカリエ 10階  ← Building name, floor

The condensed written form collapses the last three levels into hyphens: 渋谷 2-21-1. But structurally, all eight levels are present.

There are also two valid orderings depending on context:

  • Domestic mail (Japanese recipients): general → specific, written in Japanese script
  • International mail (non-Japanese carriers): specific → general, reversed so Western carriers can read it

A form that ignores this distinction will either produce addresses that Japanese postal services can't route, or international labels that overseas carriers can't parse — or both.

What the Google Maps API returns

When you geocode a Japanese address, Google Maps returns the components like this:

API field Contains Example
administrative_area_level_1 Prefecture Tokyo
locality City/municipality Minato City
sublocality_level_1 Ward/district (区) Minato
sublocality_level_2 Neighborhood (町) Shibakōen
sublocality_level_3 Chōme (丁目) 4-chōme
sublocality_level_4 Ban (番) 2
premise Building number or name Tokyo Tower
subpremise Room/floor 10F

There's a known ambiguity in major cities. In Tokyo, the ward (Shibuya-ku) can appear at either locality or sublocality_level_1 depending on how the query resolves. An extractor that only reads locality will sometimes miss the ward entirely.

Extracting the components

The extractor needs to handle all eight levels and assemble them correctly. The street-level fields (address_line_1, address_line_2) carry everything below city:

// Build address_line_1: {chōme}-{ban}-{building_number} {neighborhood}
// e.g. "4-chōme-2-8 Shibakōen"
$addressNumberParts = array_filter([$sublocality3, $sublocality4, $premiseAddressNumber]);
$addressNumber = implode('-', $addressNumberParts);
$localityPart  = $sublocality2 ?: $neighborhood;
$addressLine1  = implode(' ', array_filter([$addressNumber, $localityPart]));

// Build address_line_2: building name + room number
// Kept separate for correct duplicate detection
// (different rooms in the same building are different addresses)
$addressLine2 = implode(' ', array_filter([$premiseBuildingName, $subpremise]));

The premise field needs special handling. Google sometimes returns a building number ("4") and a building name ("Tokyo Tower") as separate premise components, or returns both merged. We separate them: numbers go into address_line_1 as part of the hyphen sequence; named buildings go into address_line_2.

protected function isAddressNumber(string $premise): bool
{
    // If it contains building patterns (ビル, タワー, マンション...), it's a name
    if ($this->containsJapaneseBuildingPattern($premise)) {
        return false;
    }

    // Hyphenated number sequences: "1-1-1", "4-2-8"
    if (preg_match('/^\d+(-\d+)+$/', $premise)) {
        return true;
    }

    // Contains chōme marker
    if (mb_strpos($premise, 'chōme') !== false || mb_strpos($premise, '丁目') !== false) {
        return true;
    }

    return false;
}

Building name detection covers both Japanese script patterns (ビル, タワー, マンション, ハイツ, 号室, 階...) and their English equivalents (Building, Tower, Apartment) since Google returns both depending on the query language.

Two address templates

Each country has two distinctive address formats - domestic and international - Japan's look like this:

// Domestic (for Japanese recipients)
〒%postal_code
%administrative_area%locality
%address_line_1
%address_line_2
%organization
%last_name %first_name

// International (for overseas carriers)
%last_name %first_name
%organization
%address_line_1
%address_line_2
%locality, %administrative_area
%postal_code

The domestic template follows the official jūkyo hyōji format — postal code first, then general to specific. The international template reverses it so Western carriers can process it without confusion.

One small detail: when Japanese script and Latin text appear adjacent — a prefecture name in Japanese followed by a romanized city name, for instance — a space needs to be inserted at the script boundary. 東京都 Minato City looks right; 東京都Minato City doesn't. The formatter handles this automatically.

Applying country-aware formatting

For shipping specifically: assembling the wrong components in the wrong fields produces addresses that look plausible in your database but fail at the carrier. Getting Japan right is a matter of understanding that it isn't just a Western address written backwards — the hierarchy, the script handling, and the two format conventions all need to be correct simultaneously.

What the form actually shows

Adapting the form for Japan doesn't mean every level of the hierarchy gets its own visible field — that would mean eight fields for one address.

The country-aware form shows top level subdivision inputs: a Prefecture dropdown and a City field. Everything below city level — ward, neighborhood, chōme, block, building number — gets assembled into address_line_1 by the extractor when the user geocodes the address. Building name and room go into address_line_2.

The adaptation is in the labels (Prefecture, not State), the subdivision data (47 prefectures), the postal code validation pattern (\d{3}-?\d{4}), and the two format templates — not in exposing all eight hierarchy levels as form fields.

Referencing subdivisions by IDs

If you store subdivisions as text, 東京都 and Tokyo and Tokyo Metropolis are three different values in a GROUP BY. Reports don't add up. Storing foreign key IDs against a normalized subdivision table means they're the same record regardless of how the user typed it or which script it came from.

Whether you choose to store your subdivision definitions in a table or elsewhere, having an immutable source of truth for each country's subdivision hierarchy supports high granularity in reporting and BI.


The extractor described here is part of Filament Address Pro, which also includes dedicated extractors for Chinese and Korean addresses. The package handles all 256 countries and territories. Japan, China, and South Korea have custom extraction logic for their specific hierarchy and script requirements.