turquoiseowl / i18n

Smart internationalization for ASP.NET
Other
556 stars 156 forks source link

UrlLocalizer.QuickUrlExclusionFilter doesn't work for # #380

Closed pheurteladding closed 5 years ago

pheurteladding commented 5 years ago

Hi turquoiseowl,

Thank you for your great work.

I encounter a problem with UrlLocalizer.QuickUrlExclusionFilter and the # char: UrlLocalizer.QuickUrlExclusionFilter = new Regex(@"(^\#)|(^\/Scripts\/dist\/vendors.*)|(^\/assets\/styleguide)|((sitemap\.xml|\.css|\.less|\.jpg|\.jpeg|\.png|\.gif|\.ico|\.svg|\.woff|\.woff2|\.ttf|\.eot|\.pdf)$)", RegexOptions.IgnoreCase);

I put this configuration because in some of my JS scripts, there is some code like: myHtmlCode = '<a class="c-showcase" href="#my-anchor">[[[The link]]]</a>'; The URL in this link must not be localized. Indeed, this would target the script itself instead of the page that uses the script. That is the reason why I setted up the QuickUrlExclusionFilter parameter.

But

Despite the QuickUrlExclusionFilter configuration, i18n continues to localize my href.

turquoiseowl commented 5 years ago

If you use (\#) instead of (^\#) does that then work?

turquoiseowl commented 5 years ago

BTW - I don't think # needs to be escaped in regex.

pheurteladding commented 5 years ago

The Regex works, I've tested it ;-) And I prefer escape the # char because it can mean comment : https://docs.microsoft.com/en-us/dotnet/standard/base-types/miscellaneous-constructs-in-regular-expressions#end-of-line-comment

I use(\#) instead of (^\#) because I need href="/my-path/my-page.html#my-anchor to be localized.

turquoiseowl commented 5 years ago

Can we close this? thanks

pheurteladding commented 5 years ago

The regex works perfectly (I've tested it), but i18n localizes URLs starting with # whereas the regex says not to do so.

turquoiseowl commented 5 years ago

Would you confirm the precise URL string in the resulting HTML response? I'm wondering whether you get a full URL (starting with http(s)) or a page-relative one (starting with #) or something in between even. Thanks.

pheurteladding commented 5 years ago

The following script: webpackJsonp([2],{299:function(e,t){e.exports='<a class="c-showcase" ng-class="{ \'c-showcase--portrait\': $ctrl.isPortrait }" href="#">\r\n <div class="c-showcase__sheet" ng-if="$ctrl.isDefault">\r\n <c-svg class="c-icon c-showcase__icon" width="40" height="40" sprite="{{ $ctrl.icon }}"></c-svg>\r\n <p class="c-showcase__title">{{ $ctrl.showcaseTitle }}</p>\r\n </div>\r\n\r\n <img alt="" class="c-showcase__picture" ng-src="{{ $ctrl.image || \'http://via.placeholder.com/240x300\' }}" ng-if="!$ctrl.isDefault" />\r\n</a>\r\n'}},[688]); //# sourceMappingURL=front.4b4b9f23206deff12b0f.js.map

is transformed into: webpackJsonp([2],{299:function(e,t){e.exports='<a class="c-showcase" ng-class="{ \'c-showcase--portrait\': $ctrl.isPortrait }" href="/fr/Scripts/dist/front.4b4b9f23206deff12b0f.js?036a0632d06bfbd9944a#">\r\n <div class="c-showcase__sheet" ng-if="$ctrl.isDefault">\r\n <c-svg class="c-icon c-showcase__icon" width="40" height="40" sprite="{{ $ctrl.icon }}"></c-svg>\r\n <p class="c-showcase__title">{{ $ctrl.showcaseTitle }}</p>\r\n </div>\r\n\r\n <img alt="" class="c-showcase__picture" ng-src="{{ $ctrl.image || \'http://via.placeholder.com/240x300\' }}" ng-if="!$ctrl.isDefault" />\r\n</a>\r\n'}},[688]); //# sourceMappingURL=front.4b4b9f23206deff12b0f.js.map

so href="#" => href="/fr/Scripts/dist/front.4b4b9f23206deff12b0f.js?036a0632d06bfbd9944a#"

turquoiseowl commented 5 years ago

Okay, well we have an explanation as to why the regex ^\# doesn't match the URL then?

pheurteladding commented 5 years ago

Actually, Among other URLs, my regex exludes all URLs starting with #. Then href="#" should not be transformed into href="/fr/Scripts/dist/front.4b4b9f23206deff12b0f.js?036a0632d06bfbd9944a#"

turquoiseowl commented 5 years ago

Sorry, I'm not with you. Please clarify precisely what the issue is that I can help you with. Thank you.

pheurteladding commented 5 years ago

I use the UrlLocalizer.QuickUrlExclusionFilter to not transform URLs starting with the # char: UrlLocalizer.QuickUrlExclusionFilter = new Regex(@"(^\#)|(^\/Scripts\/dist\/vendors.*)|(^\/assets\/styleguide)|((sitemap\.xml|\.css|\.less|\.jpg|\.jpeg|\.png|\.gif|\.ico|\.svg|\.woff|\.woff2|\.ttf|\.eot|\.pdf)$)", RegexOptions.IgnoreCase); I have tested this regex: when I put a string starting with #, the test returns true.

The problem is that i18n transforms the following JS file: webpackJsonp([2],{299:function(e,t){e.exports='<a class="c-showcase" ng-class="{ \'c-showcase--portrait\': $ctrl.isPortrait }" href="#">\r\n <div class="c-showcase__sheet" ng-if="$ctrl.isDefault">\r\n <c-svg class="c-icon c-showcase__icon" width="40" height="40" sprite="{{ $ctrl.icon }}"></c-svg>\r\n <p class="c-showcase__title">[[[Hello]]]</p>\r\n </div>\r\n\r\n <img alt="" class="c-showcase__picture" ng-src="{{ $ctrl.image || \'http://via.placeholder.com/240x300\' }}" ng-if="!$ctrl.isDefault" />\r\n</a>\r\n'}},[688]); //# sourceMappingURL=front.4b4b9f23206deff12b0f.js.map into webpackJsonp([2],{299:function(e,t){e.exports='<a class="c-showcase" ng-class="{ \'c-showcase--portrait\': $ctrl.isPortrait }" href="/fr/Scripts/dist/front.4b4b9f23206deff12b0f.js?036a0632d06bfbd9944a#">\r\n <div class="c-showcase__sheet" ng-if="$ctrl.isDefault">\r\n <c-svg class="c-icon c-showcase__icon" width="40" height="40" sprite="{{ $ctrl.icon }}"></c-svg>\r\n <p class="c-showcase__title">Hello</p>\r\n </div>\r\n\r\n <img alt="" class="c-showcase__picture" ng-src="{{ $ctrl.image || \'http://via.placeholder.com/240x300\' }}" ng-if="!$ctrl.isDefault" />\r\n</a>\r\n'}},[688]); //# sourceMappingURL=front.4b4b9f23206deff12b0f.js.map

href="#" should not be transformed into href="/fr/Scripts/dist/front.4b4b9f23206deff12b0f.js?036a0632d06bfbd9944a#" because it should have been filtered by the UrlLocalizer.QuickUrlExclusionFilter

turquoiseowl commented 5 years ago

Right, apologies for being a bit slow here. The code that uses QuickUrlExclusionFilter (and not something else which is what I was questioning) does indeed fill out the href URL before matching against the regex.

There is however a workaround whereby you can match against the href URL string as is. This can be done by adding a function to the OutgoingUrlFilters collection, something like the following:

protected void Application_Start()
{
    ...
    i18n.UrlLocalizer.OutgoingUrlFilters += delegate(string url, Uri currentRequestUrl) {
        return i18n.UrlLocalizer.QuickUrlExclusionFilter.Match(url).Success;
    };
    ...
}

Arguably this is how the QuickUrlExclusionFilter filter should work anyway - although the doc for it does state that it matches against the local path. Plus, altering it would be a breaking change for some.

Both settings are documented here: https://github.com/turquoiseowl/i18n#exclude-urls-from-being-localized

pheurteladding commented 5 years ago

Inverting the return value of the OutgoingUrlFilters seems working:

protected void Application_Start()
{
    ...
    i18n.UrlLocalizer.OutgoingUrlFilters += delegate(string url, Uri currentRequestUrl) {
        return !i18n.UrlLocalizer.QuickUrlExclusionFilter.Match(url).Success;
    };
    ...
}

Thank you very much for the help. Also, the doc doesn't explain the difference between IncomingUrlFilters and OutgoingUrlFilters.

You can close the issue.

turquoiseowl commented 5 years ago

Great, thanks for the update.