diff --git a/portal-impl/src/com/liferay/portal/servlet/filters/i18n/I18nFilter.java b/portal-impl/src/com/liferay/portal/servlet/filters/i18n/I18nFilter.java
index ad2b74b5e97a4b8d55a4845095c25ef9f5dccd10..24d324bbaa7f30ad40ff11047ff45138c1dbb8bd 100644
--- a/portal-impl/src/com/liferay/portal/servlet/filters/i18n/I18nFilter.java
+++ b/portal-impl/src/com/liferay/portal/servlet/filters/i18n/I18nFilter.java
@@ -14,6 +14,7 @@
 
 package com.liferay.portal.servlet.filters.i18n;
 
+import com.liferay.petra.string.StringBundler;
 import com.liferay.petra.string.StringPool;
 import com.liferay.portal.kernel.exception.PortalException;
 import com.liferay.portal.kernel.language.LanguageUtil;
@@ -24,15 +25,22 @@ import com.liferay.portal.kernel.model.LayoutSet;
 import com.liferay.portal.kernel.model.User;
 import com.liferay.portal.kernel.service.GroupLocalServiceUtil;
 import com.liferay.portal.kernel.servlet.HttpMethods;
+import com.liferay.portal.kernel.servlet.URLPathProcessor;
 import com.liferay.portal.kernel.util.CookieKeys;
+import com.liferay.portal.kernel.util.GetterUtil;
 import com.liferay.portal.kernel.util.JavaConstants;
 import com.liferay.portal.kernel.util.LocaleUtil;
 import com.liferay.portal.kernel.util.PortalUtil;
+import com.liferay.portal.kernel.util.PropsUtil;
 import com.liferay.portal.kernel.util.StringUtil;
 import com.liferay.portal.kernel.util.Validator;
 import com.liferay.portal.kernel.util.WebKeys;
 import com.liferay.portal.servlet.filters.BasePortalFilter;
 import com.liferay.portal.util.PropsValues;
+import com.liferay.registry.Filter;
+import com.liferay.registry.Registry;
+import com.liferay.registry.RegistryUtil;
+import com.liferay.registry.ServiceTracker;
 
 import java.util.Collections;
 import java.util.HashSet;
@@ -40,6 +48,7 @@ import java.util.Locale;
 import java.util.Set;
 
 import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
@@ -68,6 +77,28 @@ public class I18nFilter extends BasePortalFilter {
 		_languageIds = Collections.unmodifiableSet(_languageIds);
 	}
 
+	@Override
+	public void destroy() {
+		_serviceTracker.close();
+
+		super.destroy();
+	}
+
+	@Override
+	public void init(FilterConfig filterConfig) {
+		super.init(filterConfig);
+
+		Registry registry = RegistryUtil.getRegistry();
+
+		Filter filter = registry.getFilter(
+			StringBundler.concat(
+				"(objectClass=", URLPathProcessor.class.getName(), ")"));
+
+		_serviceTracker = registry.trackServices(filter);
+
+		_serviceTracker.open();
+	}
+
 	@Override
 	public boolean isFilterEnabled(
 		HttpServletRequest httpServletRequest,
@@ -112,10 +143,14 @@ public class I18nFilter extends BasePortalFilter {
 		return friendlyURL;
 	}
 
-	protected String getRedirect(HttpServletRequest httpServletRequest)
+	protected String getRedirect(
+			HttpServletRequest httpServletRequest,
+			HttpServletResponse httpServletResponse)
 		throws Exception {
 
-		if (PropsValues.LOCALE_PREPEND_FRIENDLY_URL_STYLE == 0) {
+		if ((PropsValues.LOCALE_PREPEND_FRIENDLY_URL_STYLE == 0) &&
+			!_LOCALE_FRIENDLY_URL_LAYOUT_TARGET_LOCALE) {
+
 			return null;
 		}
 
@@ -125,21 +160,9 @@ public class I18nFilter extends BasePortalFilter {
 			return null;
 		}
 
-		String contextPath = PortalUtil.getPathContext();
-
-		String requestURI = httpServletRequest.getRequestURI();
-
-		if (Validator.isNotNull(contextPath) &&
-			requestURI.startsWith(contextPath)) {
-
-			requestURI = requestURI.substring(contextPath.length());
-		}
-
-		requestURI = StringUtil.replace(
-			requestURI, StringPool.DOUBLE_SLASH, StringPool.SLASH);
-
 		String i18nLanguageId = prependI18nLanguageId(
-			httpServletRequest, PropsValues.LOCALE_PREPEND_FRIENDLY_URL_STYLE);
+			httpServletRequest, httpServletResponse,
+			PropsValues.LOCALE_PREPEND_FRIENDLY_URL_STYLE);
 
 		if (i18nLanguageId == null) {
 			return null;
@@ -151,6 +174,9 @@ public class I18nFilter extends BasePortalFilter {
 			return null;
 		}
 
+		String requestURI = _stripContextPath(
+			httpServletRequest.getRequestURI());
+
 		String i18nPathLanguageId = PortalUtil.getI18nPathLanguageId(
 			locale, i18nLanguageId);
 
@@ -160,6 +186,8 @@ public class I18nFilter extends BasePortalFilter {
 			return null;
 		}
 
+		String contextPath = PortalUtil.getPathContext();
+
 		String redirect = contextPath + i18nPath + requestURI;
 
 		int[] groupFriendlyURLIndex = PortalUtil.getGroupFriendlyURLIndex(
@@ -218,7 +246,8 @@ public class I18nFilter extends BasePortalFilter {
 	}
 
 	protected String getRequestedLanguageId(
-		HttpServletRequest httpServletRequest, String userLanguageId) {
+		HttpServletRequest httpServletRequest,
+		HttpServletResponse httpServletResponse, String userLanguageId) {
 
 		HttpSession session = httpServletRequest.getSession();
 
@@ -226,6 +255,26 @@ public class I18nFilter extends BasePortalFilter {
 
 		String requestedLanguageId = null;
 
+		if (_LOCALE_FRIENDLY_URL_LAYOUT_TARGET_LOCALE) {
+			Locale requestedLocaleFromLayoutFriendlyURL =
+				getRequestedLocaleFromLayoutURL(httpServletRequest);
+
+			if ((requestedLocaleFromLayoutFriendlyURL != null) &&
+				((locale == null) ||
+				 !locale.equals(requestedLocaleFromLayoutFriendlyURL))) {
+
+				locale = requestedLocaleFromLayoutFriendlyURL;
+
+				// this is needed for the cases where I18nFilter does not
+				// redirect to the target locale
+
+				session.setAttribute(WebKeys.LOCALE, locale);
+
+				LanguageUtil.updateCookie(
+					httpServletRequest, httpServletResponse, locale);
+			}
+		}
+
 		if (locale != null) {
 			requestedLanguageId = LocaleUtil.toLanguageId(locale);
 		}
@@ -242,6 +291,29 @@ public class I18nFilter extends BasePortalFilter {
 		return requestedLanguageId;
 	}
 
+	protected Locale getRequestedLocaleFromLayoutURL(
+		HttpServletRequest httpServletRequest) {
+
+		URLPathProcessor urlPathProcessor = getURLPathProcessor();
+
+		if (urlPathProcessor != null) {
+			try {
+				return urlPathProcessor.getLocaleFromLayoutURL(
+					httpServletRequest);
+			}
+			catch (PortalException portalException) {
+				if (_log.isDebugEnabled()) {
+					_log.debug(portalException, portalException);
+				}
+				else if (_log.isWarnEnabled()) {
+					_log.warn(portalException, portalException);
+				}
+			}
+		}
+
+		return null;
+	}
+
 	protected String getSiteDefaultLanguageId(
 		HttpServletRequest httpServletRequest) {
 
@@ -267,6 +339,10 @@ public class I18nFilter extends BasePortalFilter {
 		}
 	}
 
+	protected URLPathProcessor getURLPathProcessor() {
+		return _serviceTracker.getService();
+	}
+
 	protected boolean isAlreadyFiltered(HttpServletRequest httpServletRequest) {
 		if (httpServletRequest.getAttribute(SKIP_FILTER) != null) {
 			return true;
@@ -297,7 +373,8 @@ public class I18nFilter extends BasePortalFilter {
 	}
 
 	protected String prependI18nLanguageId(
-		HttpServletRequest httpServletRequest, int prependFriendlyUrlStyle) {
+		HttpServletRequest httpServletRequest,
+		HttpServletResponse httpServletResponse, int prependFriendlyUrlStyle) {
 
 		User user = (User)httpServletRequest.getAttribute(WebKeys.USER);
 
@@ -308,7 +385,7 @@ public class I18nFilter extends BasePortalFilter {
 		}
 
 		String requestedLanguageId = getRequestedLanguageId(
-			httpServletRequest, userLanguageId);
+			httpServletRequest, httpServletResponse, userLanguageId);
 
 		String defaultLanguageId = getDefaultLanguageId(httpServletRequest);
 
@@ -362,7 +439,7 @@ public class I18nFilter extends BasePortalFilter {
 
 		httpServletRequest.setAttribute(SKIP_FILTER, Boolean.TRUE);
 
-		String redirect = getRedirect(httpServletRequest);
+		String redirect = getRedirect(httpServletRequest, httpServletResponse);
 
 		if (redirect == null) {
 			processFilter(
@@ -379,8 +456,27 @@ public class I18nFilter extends BasePortalFilter {
 		httpServletResponse.sendRedirect(redirect);
 	}
 
+	private String _stripContextPath(String requestURI) {
+		String contextPath = PortalUtil.getPathContext();
+
+		if (Validator.isNotNull(contextPath) &&
+			requestURI.startsWith(contextPath)) {
+
+			requestURI = requestURI.substring(contextPath.length());
+		}
+
+		return StringUtil.replace(
+			requestURI, StringPool.DOUBLE_SLASH, StringPool.SLASH);
+	}
+
+	private static final boolean _LOCALE_FRIENDLY_URL_LAYOUT_TARGET_LOCALE =
+		GetterUtil.getBoolean(
+			PropsUtil.get("locale.friendly.url.layout.target.locale"));
+
 	private static final Log _log = LogFactoryUtil.getLog(I18nFilter.class);
 
 	private static Set<String> _languageIds;
 
+	private ServiceTracker<URLPathProcessor, URLPathProcessor> _serviceTracker;
+
 }
\ No newline at end of file