diff --git a/addressbook/gui/widgets/Makefile.am b/addressbook/gui/widgets/Makefile.am
index 511876a..e6ae5ca 100644
--- a/addressbook/gui/widgets/Makefile.am
+++ b/addressbook/gui/widgets/Makefile.am
@@ -1,5 +1,5 @@
 ruledir = $(privdatadir)
-rule_DATA = addresstypes.xml
+rule_DATA = addresstypes.xml address_formats.dat countrytransl.map
 
 noinst_LTLIBRARIES = libeabwidgets.la
 
@@ -29,6 +29,8 @@ libeabwidgets_la_SOURCES =			\
 	eab-config.c				\
 	eab-contact-display.c			\
 	eab-contact-display.h			\
+	eab-contact-display-address.c		\
+	eab-contact-display-address.h		\
 	eab-gui-util.c				\
 	eab-gui-util.h				\
 	e-minicard.c				\
diff --git a/addressbook/gui/widgets/eab-contact-display-address.c b/addressbook/gui/widgets/eab-contact-display-address.c
index e69de29..ee75d05 100644
--- a/addressbook/gui/widgets/eab-contact-display-address.c
+++ b/addressbook/gui/widgets/eab-contact-display-address.c
@@ -0,0 +1,580 @@
+/*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2 of the License, or (at your option) version 3.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with the program; if not, see <http://www.gnu.org/licenses/>
+*
+*
+* Authors:
+*              Dan Vratil <dvratil@redhat.com>
+*
+* Based on KDE PIM LibKABC code by Cornelius Schumacher
+*/
+
+
+#include "eab-contact-display-address.h"
+#include "e-util/e-util-private.h"
+
+#include <locale.h>
+#include <string.h>
+
+// Template tags for address formatting localization
+#define ADDRESS_REALNAME   			"%n"
+#define ADDRESS_REALNAME_UPPER			"%N"
+#define ADDRESS_COMPANY				"%cm"
+#define ADDRESS_COMPANY_UPPER			"%CM"
+#define ADDRESS_POBOX				"%p"
+#define ADDRESS_STREET				"%s"
+#define ADDRESS_STREET_UPPER			"%S"
+#define ADDRESS_ZIPCODE				"%z"
+#define ADDRESS_LOCATION			"%l"
+#define ADDRESS_LOCATION_UPPER			"%L"
+#define ADDRESS_REGION				"%r"
+#define ADDRESS_REGION_UPPER			"%R"
+#define ADDRESS_NEWLINE				"\n"
+#define ADDRESS_CONDCOMMA			"%,"	/* Conditional comma is removed when a surrounding tag is evaluated to zero */
+#define ADDRESS_CONDWHITE			"%w"	/* Conditional whitespace is removed when a surrounding tag is evaluated to zero */
+#define ADDRESS_COND_PURGEEMPTY			"%0"	/* Purge empty has following syntax: %0(...) and is removed when no tag within () is evaluated non-zero */
+
+#define ADDRESS_DEFAULT_FORMAT 			"%0(%n\n)%0(%cm\n)%0(%s\n)%0(PO BOX %p\n)%0(%l%w%r)%,%z"
+#define ADDRESS_DEFAULT_COUNTRY_POSITION	"below"
+
+
+/* Returns lower-case country code from current locales
+   (e.g. from "en_US" returns "us") */
+static gchar*
+get_system_country ()
+{
+	gchar *locale = g_strdup (setlocale (LC_ADDRESS, NULL));
+	/* Split "en_US.UTF-8" to "en" and "US.UTF-8" */
+	gchar **split = g_strsplit (locale, "_", 2);
+	/* Convert "US.UTF-8" to "us.utf-8" */
+	gchar *country_lower = g_utf8_strdown (split[1], -1);
+	gchar *dot = g_strrstr (country_lower, ".\0"); /* Freed with country_lower */
+	gchar *country = g_malloc (4); /* Should be enough */
+
+	/* Copy first N-1 characters of the country code where N is position of the dot */
+	g_utf8_strncpy (country, country_lower, dot-country_lower);
+
+	g_strfreev (split);
+	g_free (country_lower);
+	g_free (locale);
+
+	return country;
+}
+
+
+/* Returns upper-case language code from current locales
+   (e.g. from "en_US" returns "EN") */
+static gchar*
+get_system_language()
+{
+	gchar *locale = g_strdup (setlocale (LC_ADDRESS, NULL));
+	/* Find position of underscore */
+	gchar *underscore = g_strrstr (locale, "_\0"); /* Freed with locale */
+	gchar *lang_lower = g_malloc (4);
+	gchar *lang;
+
+	/* If no underscore is found, then assume no language is set and return empy string */
+	if (!underscore) {
+		g_free (locale);
+		g_free (lang_lower);
+		return g_strdup ("\0");
+	}
+
+	/* Copy first N-1 characters, where N is position of the underscore */
+	g_utf8_strncpy (lang_lower, locale, (underscore-locale));
+	lang = g_utf8_strup (lang_lower, -1);
+
+	g_free (lang_lower);
+	g_free (locale);
+	return lang;
+}
+
+/* Returns locale-like string in format "country_LANGUAGE" (which is reversed
+   compared to normal locales ("language_COUNTRY"), but we rather
+   care for the country, then for the language */
+static gchar*
+get_locale_string()
+{
+	gchar *country = get_system_country();
+	gchar *lang = get_system_language();
+
+	gchar *result = g_strconcat (country, "_", lang, NULL);
+
+	g_free (country);
+	g_free (lang);
+
+	return result;
+}
+
+/* Reads countrytransl.map file, which contains map of localized
+   country names and their ISO codes and tries to find matching record
+   for given country.
+   When no record is found (country is probably in untranslated language), returns
+   code of local computer country (from locales)
+*/
+static gchar*
+countryToISO (const gchar *country)
+{
+	FILE *file = fopen (EVOLUTION_RULEDIR "/countrytransl.map", "r");
+	gchar buffer[100];
+	gint length = 100;
+	gchar **pair;
+
+	if (!file)
+		return get_system_country();
+
+	while (fgets (buffer, length, file) != NULL)
+	{
+		pair = g_strsplit ((const gchar*)buffer, "\t", 2);
+		if (g_ascii_strcasecmp (pair[0], country) == 0)
+		{
+			gchar *ret = g_strdup (pair[0]);
+			fclose (file);
+			g_strfreev (pair);
+			g_free (buffer);
+			return ret;
+		}
+		g_strfreev (pair);
+	}
+
+	/* If we get here, then no match was found in the map file and we
+	   fallback to local system locales */
+	fclose (file);
+	return get_system_country();
+}
+
+
+/* Tries to find given key in "country_LANGUAGE" group. When fails to  find
+   such group, then fallbacks to "country" group. When such group does not
+   exist either, NULL is returned */
+static gchar*
+get_key_file_locale_string (GKeyFile *key_file, const gchar *key, const gchar *locale)
+{
+	gchar *result;
+	gchar *group;
+
+	/* Default locale is in "country_LANG", but such group may not exist. In such case use group "country" */
+	if (g_key_file_has_group (key_file, locale))
+		group = g_strdup (locale);
+	else {
+		gchar **locales = g_strsplit (locale, "_", 0);
+		group = g_strdup (locales[0]);
+		g_strfreev (locales);
+	}
+
+	/* When group or key does not exist, returns NULL and fallback string will be used */
+	result = g_key_file_get_string (key_file, group, key, NULL);
+
+	g_free (group);
+	return result;
+}
+
+
+/* Gets localized format from address_formats.dat which is a key file.
+   When key for given locales is not found, the fallback key is used. */
+static void
+get_home_address_format (gchar **format, gchar **country_position, const gchar *locale)
+{
+	GKeyFile *key_file;
+	gchar *loc;
+
+	if (locale == NULL)
+		loc = get_locale_string();
+	else
+		loc = g_strdup (locale);
+
+	key_file = g_key_file_new();
+	if (!g_key_file_load_from_file (key_file, EVOLUTION_RULEDIR "/address_formats.dat", 0, NULL)) {
+		*format = g_strdup (ADDRESS_DEFAULT_FORMAT);
+		*country_position = g_strdup(ADDRESS_DEFAULT_COUNTRY_POSITION);
+		g_key_file_free (key_file);
+		g_free (loc);
+		return;
+	}
+
+	if (format) {
+		*format = get_key_file_locale_string (key_file, "AddressFormat", loc);
+		if (!*format)
+			*format = g_strdup (ADDRESS_DEFAULT_FORMAT);
+	}
+
+	if (country_position) {
+		*country_position = get_key_file_locale_string (key_file, "CountryPosition", locale);
+		if (!*country_position)
+			*country_position = g_strdup (ADDRESS_DEFAULT_COUNTRY_POSITION);
+	}
+
+	g_free (loc);
+	g_key_file_free (key_file);
+}
+
+/* Some countries have different home and business address formatting. When no record for
+   business address format in found for given locales, format for home address is used. */
+static void
+get_business_address_format (gchar **format, gchar **country_position, const gchar *locale)
+{
+	GKeyFile *key_file;
+	gchar *loc;
+
+	if (locale == NULL)
+		loc = get_locale_string();
+	else
+		loc = g_strdup(locale);
+
+	key_file = g_key_file_new();
+	if (!g_key_file_load_from_file (key_file, EVOLUTION_RULEDIR "/address_formats.dat", 0, NULL)) {
+		*format = g_strdup (ADDRESS_DEFAULT_FORMAT);
+		*country_position = g_strdup(ADDRESS_DEFAULT_COUNTRY_POSITION);
+		g_key_file_free (key_file);
+		g_free (loc);
+		return;
+	}
+
+	if (format) {
+		*format = get_key_file_locale_string (key_file, "BusinessAddressFormat", loc);
+		if (!*format)
+			get_home_address_format (format, NULL, loc);
+	}
+
+	if (country_position) {
+		*country_position = get_key_file_locale_string (key_file, "BusinessCountryPosition", loc);
+		if (!*country_position)
+			get_home_address_format (NULL, country_position, loc);
+	}
+
+	g_free (loc);
+	g_key_file_free (key_file);
+}
+
+
+static gint
+find_balanced_bracket (const gchar *str, gint pos)
+{
+	gint balance_counter = 0;
+	gint i;
+
+	for (i = pos+1; i < strlen (str); i++)
+	{
+		if (str[i] == ')' && balance_counter == 0)
+			return i;
+
+		if (str[i] == '(')
+			balance_counter++;
+	}
+
+	return -1;
+}
+
+
+/**
+ * Pass empty string in \replacement, to replace it by "!_P_!" placeholder, or
+ * pass NULL to really replace the variable by empty string ("")
+ */
+static gboolean
+replace_tag (gchar **text, const gchar *variable, const gchar *replacement)
+{
+	gchar *p, *next;
+	GString *str;
+	gint find_len;
+	gboolean replaced = FALSE;
+
+	g_return_val_if_fail (text, FALSE);
+	g_return_val_if_fail (variable && *variable, FALSE);
+
+	find_len = strlen (variable);
+	str = g_string_new ("");
+	p = *text;
+	while (next = strstr (p, variable), next) {
+		if (p < next)
+			g_string_append_len (str, p, next - p);
+
+		p = next + find_len;
+
+		if (replacement &&  *replacement) {
+			g_string_append (str, replacement);
+			replaced = TRUE;
+			break;
+		} else {
+			if (!replacement) {
+				replaced = TRUE;
+				break;
+			} else {
+				g_string_append (str, "!_P_!");
+				replaced = FALSE;
+				break;
+			}
+		}
+	}
+	g_string_append (str, p);
+
+	g_free (*text);
+	*text = g_strdup (str->str);
+
+	g_string_free (str, TRUE);
+
+	return replaced;
+}
+
+/* This function first parses and substitutes any bracketed sections
+   and after that replaces any tags with their values. If a bracketed
+   section or a tag evalulate to zero, they are not just removed but
+   replaced with a placeholder. This is because in the last step conditionals
+   are resolved with depend on information about zero-evaluations.
+*/
+static gboolean
+parse_address_template_section (const gchar *format,
+				gchar **result,
+				const gchar *realname,
+				const gchar *org_name,
+				EContactAddress *address)
+{
+	gboolean ret = FALSE;
+	gchar *tag;
+	gint tag_len;
+	gchar *p, *next;
+	gchar *str_up;
+
+	if (*result)
+		g_free (*result);
+
+	*result = g_strdup (format);
+
+	/* first check for brackets that have to be evaluated first */
+	tag = g_strdup (ADDRESS_COND_PURGEEMPTY);
+	tag_len = g_utf8_strlen (tag, -1);
+	p = *result;
+	while (next = strstr (p, tag), next) {
+		gint bpos1; /* Position of openning bracket */
+		gint bpos2; /* Position of closing bracket */
+		gint fpos = next - p;
+
+		bpos1 = fpos + 2; /* 2 = length of ADDRESS_COND_PURGEEMPTY  */
+
+		/* Expect opening bracket and find next balanced closing bracket. If
+		   next char is no opening bracket, continue parsing (not a valid tag) */
+		if ( (*result)[bpos1] == '(') {
+			bpos2 = find_balanced_bracket (*result, bpos1);
+			if (bpos2 != -1) {
+				gchar *rplstr;
+				gchar *sub_str = g_malloc (bpos2 - bpos1);
+				gchar *bfr1;
+				gchar *bfr2;
+				gboolean purge;
+
+				/* Get inner content of a purgeempty tag (e.g. string inbetween brackets) */
+				g_utf8_strncpy (sub_str, &((*result)[bpos1 + 1]), bpos2 - bpos1 - 1);
+
+				/* Parse it recursively */
+				purge = !parse_address_template_section (sub_str, &rplstr, realname, org_name, address);
+
+				bfr1 = g_malloc (fpos + 1);
+				bfr2 = g_malloc (strlen (*result) - bpos2);
+
+				strncpy (bfr1, *result, fpos);
+				strncpy (bfr2, &((*result)[bpos2 + 1]), strlen (*result) - bpos2 - 1);
+				bfr1[fpos] = '\0';
+				bfr2[strlen (*result) - bpos2 - 1] = '\0';
+
+				/* Now replace the purgeempty tag with string returned from the recursive call */
+				if (purge) {
+					/* !_P_! means 'delete me' */
+					g_free (*result);
+					*result = g_strconcat (bfr1, "!_P_!", bfr2, NULL);
+				} else {
+					g_free (*result);
+					*result = g_strconcat (bfr1, rplstr, bfr2, NULL);
+					ret = TRUE;
+				}
+
+				g_free (bfr1);
+				g_free (bfr2);
+				g_free (rplstr);
+				g_free (sub_str);
+			} else /* Missing bracket? Broken data. Leave. */
+				break;
+		}
+
+		p = *result;
+	}
+	g_free (tag);
+
+	/* After sorting out all purge tags, we just search'n'replace the rest,
+	   keeping track of wheter at least on tag evaluates to something. */
+	if (replace_tag (result,  ADDRESS_REALNAME, realname))
+		ret = TRUE;
+
+	str_up = (realname ? g_utf8_strup (realname, -1) : g_strdup ("\0"));
+	if (replace_tag (result, ADDRESS_REALNAME_UPPER, str_up))
+		ret = TRUE;
+	g_free (str_up);
+
+	if (replace_tag (result, ADDRESS_COMPANY, org_name))
+		ret = TRUE;
+
+	str_up = (org_name ? g_utf8_strup (org_name, -1) : g_strdup ("\0"));
+	if (replace_tag (result, ADDRESS_COMPANY_UPPER, str_up))
+		ret = TRUE;
+	g_free (str_up);
+
+	if (replace_tag (result, ADDRESS_POBOX, address->po))
+		ret = TRUE;
+
+	if (replace_tag (result, ADDRESS_STREET, address->street))
+		ret = TRUE;
+
+	str_up = (address->street ? g_utf8_strup (address->street, -1) : g_strdup ("\0"));
+	if (replace_tag (result, ADDRESS_STREET_UPPER, str_up))
+		ret = TRUE;
+	g_free (str_up);
+
+	if (replace_tag (result, ADDRESS_ZIPCODE, address->code))
+		ret = TRUE;
+
+	if (replace_tag (result, ADDRESS_LOCATION, address->locality))
+		ret = TRUE;
+
+	str_up = (address->locality ? g_utf8_strup (address->locality, -1) : g_strdup ("\0"));
+	if (replace_tag (result, ADDRESS_LOCATION_UPPER, str_up))
+		ret = TRUE;
+	g_free (str_up);
+
+	if (replace_tag (result, ADDRESS_REGION, address->region))
+		ret = TRUE;
+
+	if (replace_tag (result, ADDRESS_REGION_UPPER, address->region))
+		ret = TRUE;
+
+	while (strstr (*result, ADDRESS_NEWLINE))
+		replace_tag (result, ADDRESS_NEWLINE, "<br>");
+
+	/* Conditional comma */
+	tag = g_strdup (ADDRESS_CONDCOMMA);
+	tag_len = g_utf8_strlen (tag, -1);
+	p = *result;
+	while (next = strstr (p, tag), next)
+	{
+		gchar *str1 = g_malloc (5);
+		gchar *str2 = g_malloc (5);
+
+		g_utf8_strncpy (str1, &((*result)[next-p-5]), 5);
+		g_utf8_strncpy (str2, &((*result)[next-p+2]), 5);
+
+		/* Try to find !_P_! before or after current tag - when no found, assume there are already replaced tags
+		   and place the comma, otherwise remove the tag but does not insert anything */
+		if ((g_strcmp0 (str1, "!_P_!") != 0) && (g_strcmp0 (str2, "!_P_!") != 0))
+			replace_tag (result, tag, ", ");
+		else
+			replace_tag (result, tag, NULL);
+
+		g_free (str1);
+		g_free (str2);
+
+		p = next + tag_len;
+	}
+	g_free (tag);
+
+	/* Conditional whitespace */
+	tag = g_strdup (ADDRESS_CONDWHITE);
+	tag_len = g_utf8_strlen (tag, -1);
+	p = *result;
+	while (next = strstr (p, tag), next)
+	{
+		gchar *str1 = g_malloc (5);
+		gchar *str2 = g_malloc (5);
+
+		g_utf8_strncpy (str1, &((*result)[next-p-5]), 5);
+		g_utf8_strncpy (str2, &((*result)[next-p+2]), 5);
+
+		if ((g_strcmp0 (str1, "!_P_!") != 0) && (g_strcmp0 (str2, "!_P_!") != 0))
+			replace_tag (result, tag, " ");
+		else
+			replace_tag (result, tag, NULL);
+
+		g_free (str1);
+		g_free (str2);
+
+		p = next + tag_len;
+	}
+	g_free (tag);
+
+	while (strstr (*result, "!_P_!"))
+		replace_tag (result, "!_P_!", NULL);
+
+	return ret;
+}
+
+const gchar *
+format_address (EContact *contact,
+		EContactField address_type)
+{
+	gchar *result;
+	gchar *format;
+	gchar *country_position;
+	gchar *locale;
+	EContactAddress *addr = e_contact_get (contact, address_type);
+
+        if (!addr)
+        	return NULL;
+
+        if (!addr->po && !addr->ext && !addr->street && !addr->locality && !addr->region &&
+            !addr->code  && !addr->country) {
+            e_contact_address_free (addr);
+            return NULL;
+        }
+
+	if (addr->country) {
+		gchar *cntry = countryToISO ((const gchar*)addr->country);
+		gchar *lang = get_system_language();
+		locale = g_strconcat (cntry, "_", lang, NULL);
+		g_free (cntry);
+		g_free (lang);
+	} else
+		locale = get_locale_string();
+
+        if (address_type == E_CONTACT_ADDRESS_HOME)
+		get_home_address_format (&format, &country_position, locale);
+	else if (address_type == E_CONTACT_ADDRESS_WORK)
+		get_business_address_format (&format, &country_position, locale);
+	else return NULL;
+
+	parse_address_template_section (format, &result,
+					e_contact_get_const (contact, E_CONTACT_FULL_NAME),
+					e_contact_get_const (contact, E_CONTACT_ORG),
+					addr);
+
+	/* Add the country line. In some countries, the address can be located above the rest of address */
+	if (addr->country)
+	{
+		gchar *country_upper = g_utf8_strup (addr->country, -1);
+		gchar *p = result;
+		if (g_strcmp0 (country_position, "BELOW") == 0) {
+			result = g_strconcat (p, "<br><br>", country_upper, NULL);
+		} else if (g_strcmp0 (country_position, "below") == 0) {
+			result = g_strconcat (p, "<br><br>", addr->country, NULL);
+		} else if (g_strcmp0 (country_position, "ABOVE") == 0) {
+			result = g_strconcat (country_upper, "<br><br>", p, NULL);
+		}
+		else if (g_strcmp0 (country_position, "above") == 0) {
+			result = g_strconcat (addr->country, "<br><br>", p, NULL);
+		}
+		g_free (country_upper);
+		g_free (p);
+	}
+
+	e_contact_address_free (addr);
+	g_free (format);
+	g_free (locale);
+	g_free (country_position);
+
+	return result;
+}
diff --git a/addressbook/gui/widgets/eab-contact-display-address.h b/addressbook/gui/widgets/eab-contact-display-address.h
index e69de29..302d133 100644
--- a/addressbook/gui/widgets/eab-contact-display-address.h
+++ b/addressbook/gui/widgets/eab-contact-display-address.h
@@ -0,0 +1,9 @@
+#ifndef EAB_CONTACT_DISPLAY_ADDRESS_H_
+#define EAB_CONTACT_DISPLAY_ADDRESS_H_
+
+#include <libebook/e-contact.h>
+
+const gchar* format_address	(EContact *contact, EContactField address_type);
+
+
+#endif /* EAB_CONTACT_DISPLAY_ADDRESS_H_ */
diff --git a/addressbook/gui/widgets/eab-contact-display.c b/addressbook/gui/widgets/eab-contact-display.c
index c970afe..973e0dc 100644
--- a/addressbook/gui/widgets/eab-contact-display.c
+++ b/addressbook/gui/widgets/eab-contact-display.c
@@ -26,6 +26,8 @@
 
 #include "eab-contact-display.h"
 
+#include "eab-contact-display-address.h"
+
 #include "eab-gui-util.h"
 #include "e-util/e-util.h"
 #include "e-util/e-html-utils.h"
@@ -186,48 +188,25 @@ static void
 accum_address (GString *buffer,
                EContact *contact,
                const gchar *html_label,
-               EContactField adr_field,
-               EContactField label_field)
+               EContactField adr_field)
 {
-	EContactAddress *adr;
-	const gchar *label;
-
-	label = e_contact_get_const (contact, label_field);
-	if (label) {
-		gchar *html = e_text_to_html (label, E_TEXT_TO_HTML_CONVERT_NL);
-
-		if (TEXT_IS_RIGHT_TO_LEFT)
-			g_string_append_printf (buffer, "<tr><td align=\"right\" valign=\"top\" nowrap>%s</td><td valign=\"top\" width=\"100\" align=\"right\"><font color=" HEADER_COLOR ">%s:</font></td><td valign=\"top\" width=\"" IMAGE_COL_WIDTH "\"></td></tr>", html, html_label);
-		else
-			g_string_append_printf (buffer, "<tr><td valign=\"top\" width=\"" IMAGE_COL_WIDTH "\"></td><td valign=\"top\" width=\"100\"><font color=" HEADER_COLOR ">%s:</font></td><td valign=\"top\" nowrap>%s</td></tr>", html_label, html);
+	gchar *localized_address = format_address (contact, adr_field);
 
-		g_free (html);
-		return;
-	}
-
-	adr = e_contact_get (contact, adr_field);
-	if (adr &&
-	    (adr->po || adr->ext || adr->street || adr->locality || adr->region || adr->code || adr->country)) {
+	if (localized_address) {
 		if (TEXT_IS_RIGHT_TO_LEFT)
 			g_string_append_printf (buffer, "<tr><td align=\"right\" valign=\"top\" nowrap>");
 		else
 			g_string_append_printf (buffer, "<tr><td valign=\"top\" width=\"" IMAGE_COL_WIDTH "\"></td><td valign=\"top\" width=\"100\"><font color=" HEADER_COLOR ">%s:</font></td><td valign=\"top\" nowrap>", html_label);
 
-		if (adr->po && *adr->po) g_string_append_printf (buffer, "%s<br>", adr->po);
-		if (adr->ext && *adr->ext) g_string_append_printf (buffer, "%s<br>", adr->ext);
-		if (adr->street && *adr->street) g_string_append_printf (buffer, "%s<br>", adr->street);
-		if (adr->locality && *adr->locality) g_string_append_printf (buffer, "%s<br>", adr->locality);
-		if (adr->region && *adr->region) g_string_append_printf (buffer, "%s<br>", adr->region);
-		if (adr->code && *adr->code) g_string_append_printf (buffer, "%s<br>", adr->code);
-		if (adr->country && *adr->country) g_string_append_printf (buffer, "%s<br>", adr->country);
+		g_string_append (buffer, localized_address);
 
 		if (TEXT_IS_RIGHT_TO_LEFT)
 			g_string_append_printf (buffer, "</td><td valign=\"top\" width=\"100\" align=\"right\"><font color=" HEADER_COLOR ">%s:</font></td><td valign=\"top\" width=\"" IMAGE_COL_WIDTH "\"></td></tr>", html_label);
 		else
 			g_string_append_printf (buffer, "</td></tr>");
 	}
-	if (adr)
-		e_contact_address_free (adr);
+
+	g_free (localized_address);
 }
 
 static void
@@ -548,7 +527,7 @@ render_work_block (GString *buffer, EContact *contact)
 	accum_attribute (accum, contact, _("Free/Busy"), E_CONTACT_FREEBUSY_URL, NULL, E_TEXT_TO_HTML_CONVERT_URLS);
 	accum_attribute (accum, contact, _("Phone"), E_CONTACT_PHONE_BUSINESS, NULL, 0);
 	accum_attribute (accum, contact, _("Fax"), E_CONTACT_PHONE_BUSINESS_FAX, NULL, 0);
-	accum_address   (accum, contact, _("Address"), E_CONTACT_ADDRESS_WORK, E_CONTACT_ADDRESS_LABEL_WORK);
+	accum_address   (accum, contact, _("Address"), E_CONTACT_ADDRESS_WORK);
 
 	if (accum->len > 0) {
 		start_block (buffer, _("Work"));
@@ -569,7 +548,7 @@ render_personal_block (GString *buffer, EContact *contact)
 
 	accum_attribute (accum, contact, _("Phone"), E_CONTACT_PHONE_HOME, NULL, 0);
 	accum_attribute (accum, contact, _("Mobile Phone"), E_CONTACT_PHONE_MOBILE, NULL, 0);
-	accum_address   (accum, contact, _("Address"), E_CONTACT_ADDRESS_HOME, E_CONTACT_ADDRESS_LABEL_HOME);
+	accum_address   (accum, contact, _("Address"), E_CONTACT_ADDRESS_HOME);
 	accum_time_attribute (accum, contact, _("Birthday"), E_CONTACT_BIRTH_DATE, NULL, 0);
 	accum_time_attribute (accum, contact, _("Anniversary"), E_CONTACT_ANNIVERSARY, NULL, 0);
 	accum_attribute (accum, contact, _("Spouse"), E_CONTACT_SPOUSE, NULL, 0);
