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..d2faf9545cdc84c7971f2b61489cdd8bcf5b6ade 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,7 +25,9 @@ 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;
@@ -32,7 +35,12 @@ 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.PropsUtil;
 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,7 +143,9 @@ 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) {
@@ -125,21 +158,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 +172,9 @@ public class I18nFilter extends BasePortalFilter {
 			return null;
 		}
 
+		String requestURI = _stripContextPath(
+			httpServletRequest.getRequestURI());
+
 		String i18nPathLanguageId = PortalUtil.getI18nPathLanguageId(
 			locale, i18nLanguageId);
 
@@ -160,7 +184,7 @@ public class I18nFilter extends BasePortalFilter {
 			return null;
 		}
 
-		String redirect = contextPath + i18nPath + requestURI;
+		String redirect = PortalUtil.getPathContext() + i18nPath + requestURI;
 
 		int[] groupFriendlyURLIndex = PortalUtil.getGroupFriendlyURLIndex(
 			requestURI);
@@ -198,7 +222,7 @@ public class I18nFilter extends BasePortalFilter {
 
 			if (groupFriendlyURL.equals(group.getFriendlyURL())) {
 				redirect =
-					contextPath + i18nPath +
+					PortalUtil.getPathContext() + i18nPath +
 						requestURI.substring(friendlyURLEnd);
 			}
 		}
@@ -218,7 +242,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 +251,26 @@ public class I18nFilter extends BasePortalFilter {
 
 		String requestedLanguageId = null;
 
+		if (_LAYOUT_URL_SETS_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("org.apache.struts.action.LOCALE", locale);
+
+				LanguageUtil.updateCookie(
+					httpServletRequest, httpServletResponse, locale);
+			}
+		}
+
 		if (locale != null) {
 			requestedLanguageId = LocaleUtil.toLanguageId(locale);
 		}
@@ -242,6 +287,26 @@ 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);
+				}
+			}
+		}
+
+		return null;
+	}
+
 	protected String getSiteDefaultLanguageId(
 		HttpServletRequest httpServletRequest) {
 
@@ -267,6 +332,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 +366,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 +378,7 @@ public class I18nFilter extends BasePortalFilter {
 		}
 
 		String requestedLanguageId = getRequestedLanguageId(
-			httpServletRequest, userLanguageId);
+			httpServletRequest, httpServletResponse, userLanguageId);
 
 		String defaultLanguageId = getDefaultLanguageId(httpServletRequest);
 
@@ -362,7 +432,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 +449,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 _LAYOUT_URL_SETS_LOCALE =
+		GetterUtil.getBoolean(
+			PropsUtil.get("locale.friendlyurl.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