You want to change the title of a billing field in WooCommerce checkout on your WordPress site. Maybe “Phone” should read “Mobile number”, or “ZIP Code” should read “Postal code”. Most answers tell you to use woocommerce_checkout_fields. That works for some fields. For others the old label comes back as soon as the customer picks a country, and the My Account → Addresses form never changes at all.
This snippet renames labels in the right places. Billing-only fields like name, phone and email change on checkout and on the edit-address page. Shared address parts like postcode and state keep their new label when WooCommerce’s JavaScript swaps labels for each country.
The snippet
Put it in a small plugin or in your theme’s functions.php. Edit the two label arrays at the top and leave the rest alone.
/**
* Billing-only labels, keyed by the full checkout field ID.
*/
function dpc_billing_field_labels(): array {
return [
'billing_first_name' => __( 'Given name', 'dpc' ),
'billing_last_name' => __( 'Family name', 'dpc' ),
'billing_company' => __( 'Company or organisation', 'dpc' ),
'billing_phone' => __( 'Mobile number', 'dpc' ),
'billing_email' => __( 'Email for receipts', 'dpc' ),
];
}
/**
* Address-part labels shared by billing and shipping, keyed without prefix.
*/
function dpc_address_field_labels(): array {
return [
'postcode' => __( 'Postal code', 'dpc' ),
'state' => __( 'Region', 'dpc' ),
];
}
add_filter( 'woocommerce_billing_fields', 'dpc_rename_billing_fields', 20 );
function dpc_rename_billing_fields( array $fields ): array {
foreach ( dpc_billing_field_labels() as $key => $label ) {
if ( isset( $fields[ $key ] ) ) {
$fields[ $key ]['label'] = $label;
}
}
return $fields;
}
add_filter( 'woocommerce_default_address_fields', 'dpc_rename_address_fields', 20 );
function dpc_rename_address_fields( array $fields ): array {
foreach ( dpc_address_field_labels() as $key => $label ) {
if ( isset( $fields[ $key ] ) ) {
$fields[ $key ]['label'] = $label;
}
}
return $fields;
}
// Country locales (US "ZIP Code", GB "County"…) override the defaults, on page load and in JS.
add_filter( 'woocommerce_get_country_locale', 'dpc_rename_locale_labels', 20 );
function dpc_rename_locale_labels( array $locales ): array {
$labels = dpc_address_field_labels();
foreach ( $locales as $country => $fields ) {
foreach ( $labels as $key => $label ) {
if ( isset( $fields[ $key ]['label'] ) ) {
$locales[ $country ][ $key ]['label'] = $label;
}
}
}
return $locales;
}
How it works
woocommerce_billing_fieldsruns insideWC()->countries->get_address_fields(). The classic checkout and the My Account edit-address form both use that function, so one filter covers both pages.woocommerce_checkout_fieldsonly reaches the checkout.woocommerce_default_address_fieldssets the base definition for address parts (postcode, state, city, address lines). Billing and shipping are both built from it, so a postcode renamed here changes in both forms.woocommerce_get_country_localeis why renames often seem not to work. Many countries ship their own label (“ZIP Code” for the US, “County” for the UK). On checkout,address-i18n.jswrites those labels back into the form whenever the country changes, which also happens on the first load. The filter replaces a country’s label only where that country defines one, and leaves rules likerequiredandhiddenalone.- Priority 20 runs after most plugins that hook at the default of 10. If another plugin still wins, list everything attached to the hook with this helper.
Customise it
- To rename a shipping-only field, copy
dpc_rename_billing_fieldsand hook it towoocommerce_shipping_fields, using keys likeshipping_company. - Field IDs are the
nameattributes on the checkout form:billing_country,billing_address_1,billing_city, and so on. Shared parts go indpc_address_field_labels()without the prefix. - To keep a country’s own wording (for example, US customers still see “ZIP Code”), skip that country inside the locale loop with
if ( 'US' === $country ) { continue; }. - Placeholders work the same way. Set
$fields[ $key ]['placeholder']next to the label. - The order edit screen in wp-admin uses its own filter,
woocommerce_admin_billing_fields, and its keys have no prefix (phone,company).
Gotchas
- Checkout block: this snippet is for the classic checkout (the
[woocommerce_checkout]shortcode) and My Account. The Checkout block renders its fields in React from its own definitions, sowoocommerce_billing_fieldsdoes not reach it. To check which one you use, open your checkout page in the editor and see whether it contains a Checkout block. If it does, test there before relying on these filters. - WooCommerce prints labels through
wp_kses_post(), so simple markup like<abbr>works. Labels are fixed strings here. Never build them from request data. - Keep the
__()calls with your own text domain if the store is multilingual. The strings can then be translated like any other plugin string. - Changing a label does not change the meta key. Orders still store
billing_phone, so exports and integrations keep working.
Snippet poll. Should this snippet be in the Scripts Organizer library for one-click import? 10 votes put it there.
0 of 10 votes