Open tomasr78 opened 9 years ago
Just want to add comment about your provided language selection code in Explicit User Language Selection section.
This code create duplicate URL of the same content and it is not Google friendly, should be used with care if google ranking maters.
@Html.ActionLink( linkText: nativelangname, actionName: "SetLanguage", controllerName: "Account", routeValues: new { langtag = langtag, returnUrl = Request.Url }, htmlAttributes: new { title = title } )
If a URL that is already localized is being patched on the way out, that is a bug.
Are you able to debug it? The method in question is EarlyUrlLocalizer.ProcessOutgoing. You will see that the code checks whether a URL is already localized before localizing it.
Thanks.
You misunderstood me. Let's start from simple question. I have simple code below in my demo app. If we run web page with language selector, let's say http://localhost:port/LT the href="@url" will contain patched url with language selector /lt/ but @url surounded with A tag will have absolute path "/". The generated code would be
<a href="/lt">/</a>
Does it mean that i18n looks for HREF tags and patch only url inside these tags?
var url = Request.Url.AbsolutePath;
<a href="@url">@url</a>
Does it mean that i18n looks for HREF tags and patch only url inside these tags?
Yes.
In case it helps, you can control outgoing (late) URL localization prior to it happening for a request and subject url. E.g.
protected void Application_Start()
{
...
i18n.UrlLocalizer.OutgoingUrlFilters += delegate(string url, Uri currentRequestUrl) {
Uri uri;
if (Uri.TryCreate(url, UriKind.Absolute, out uri)
|| Uri.TryCreate(currentRequestUrl, url, out uri)) {
if (uri.LocalPath.IndexOf("/Api", StringComparison.OrdinalIgnoreCase) != -1) {
return false; }
if (uri.LocalPath.IndexOf("xdomain", StringComparison.OrdinalIgnoreCase) != -1) {
return false; }
}
return true;
};
}
As a general solution, you can add a querystring to the URLs NOT to be localized and test for that in the i18n.UrlLocalizer.OutgoingUrlFilters delegate. E.g. \fr\pdf-word?nolocal
Does it mean that i18n looks for HREF tags and patch only url inside these tags? Yes.
Could you add html tag, let's say data-nolocal="true" to let exclude html href tags from modifying?
Now I face several problems without having option to control href patching.
The first one as I explained in first post to create custom language selector. Your suggested solution to use query string "\fr\pdf-word?nolocal" and then exclude url by query string is working but not perfect, it creates duplicate URL and looks more like a hack and not solution.
The second problem is with canonical html tag.
I have url http://www.domain.com/lt/terms and would like to have canonical html tag in that web page with url http://www.domain.com/terms I don't find a way to set desired url in canonical tag because i18n modify href.
It would be really useful option where I could exclude HTML tags and don't let i18n modify href.
If I understand you correctly, you suggest that the UrlLocalizer code that parses the response in order to extract URLs be modified to test for the presence of URLs in HTML tags that include an attribute along the lines of data-i18n-url-nolocal="true"
, and to ignore such URLs in that case.
That would be a nice feature. It should be possible to include that logic in the regex that currently parses for URLs. Indeed that regex could be exposed publicly to allow for complete customization. Would you care to have a stab at it yourself? I'm a bit snowed under myself at the moment. Accompanying unit tests for it would be nice too.
Everything is correct that you wrote. I will try to develop this feature and post a code!
Sorry for delay but I was busy with other projects. Today I have implemented the feature, will post to repository and let you know.
I have made changes to repository and updated with new feature, html tags with data-i18n-url-nolocal data tag attribute from now will be ignored. tested on Dev and Prod servers for one week, working as expected.
The examples "The custom language selector". Produce clear direct language selection menu without query tags.
var langs = LanguageHelpers.GetAppLanguages().OrderBy(x => x.Key).ToArray();
for (var index = 0; index < langs.Length; index++)
{
string url;
if (index == 0)
{
url = Request.Url.AbsolutePath;
}
else
{
var langTag = "/" + langs[index].Key;
url = langTag + Request.Url.AbsolutePath.TrimEnd(Convert.ToChar("/"));
}
<a data-i18n-url-nolocal href="@url">@langs[index].Value.NativeNameTitleCase</a>
}
}
Canonical link example, create simple canonical links for web pages using these rules: removes query strings, removes trailing slashes, removes EN language tag from URL, removes any language selector from URL.
Razor
@{
if (ViewData["CanonicalUrl"] != null)
{
<link data-i18n-url-nolocal rel="canonical" href="@ViewData["CanonicalUrl"]" />
}
}
Action Filter
public class CanonicalUrlAttribute : ActionFilterAttribute
{
public CanonicalUrlAttribute()
{
IncludeLangTag = true;
}
public bool IncludeLangTag { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.Request.Url != null)
{
var absolutePath = filterContext.HttpContext.Request.Url.ToString();
if (IncludeLangTag)
{
var langTag = filterContext.HttpContext.GetPrincipalAppLanguageForRequest();
var host = filterContext.HttpContext.Request.Url.Authority;
var newHost = host + "/" + langTag;
absolutePath = absolutePath.Replace(host, newHost);
}
//Removing query string
absolutePath = absolutePath.RemoveRight("?");
//Removing trailing slash
absolutePath = absolutePath.TrimEnd(Convert.ToChar("/"));
//Removing EN language tag from URL
absolutePath = absolutePath.Replace("/en", "");
filterContext.Controller.ViewData["CanonicalUrl"] = absolutePath;
}
base.OnActionExecuting(filterContext);
}
}
Controller
//These rules will be applied to all actions: removes query strings, removes trailing slashes, removes EN language tag from URL
[CanonicalUrl]
public class HomeController : Controller
{
}
//These rules will be applied to all actions: removes query strings, removes trailing slashes, removes EN language tag from URL
//Additional rules will be applied: removes any language selector from URL
//It means that all /terms web pages will have canonical tags without language tag. Useful if no translation is available for a web page to let search engine know that it is the same page with different urls.
[CanonicalUrl(IncludeLangTag=false)]
public ActionResult Terms()
{
return View("Terms");
}
I have committed data-i18n-url-nolocal feature implementation half year ago but it seems it is missing in new release. Have you implemented your own solution to ignore HREF tags localization?
I can't remember either adding or removing it. Was there a Pull Request? Was it just a change to UrlsToExcludeFromProcessing
?
I have submitted pull request and it is missing in latest releases. I also submitted tests and tested my implementation in production and it works perfectly.
And no, it is not the same as UrlsToExcludeFromProcessing. The UrlsToExcludeFromProcessing is global exclusion and my implementation of data-i18n-url-nolocal data html tag can be used on certain html tags to exclude localization.
I am trying to develop custom language selection menu. Just simple menu where available languages listed with direct url to translated web pages.
The problem with code above is that HREF of A element automatically pre-tagged with language tag. I do it by myself but it seems that i18n do this automatically too.
Let's say I am at page
https://localhost:44301/lt/pdf-word
The HTML code generated by code above will look like
i18n automatically parsed HREF tag and added additional /LT/ language tag for English HREF.
Is it possible to disable HREF tagging for some A HTML elements or any other solution to solve the problem?
p.s. If I output value @url in razor view as text I get correct url
/pdf-word <-Not tagged, as needed! /lt/pdf-word