Coder Social home page Coder Social logo

routelocalization's People

Contributors

dresel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

routelocalization's Issues

Object reference not set to an instance of an object

What could be the reason for getting the above exception when doing route translation registration:

        localization.ForCulture("en")
            .ForController<DirectoryCategoryController>()
            .ForAction(x => x.Directory())
            .AddTranslation("directory");

Disable Route translation in API not working

Hello,

I am working on a project to which I will add route localization in the future.
I decided to add RouteLocalization to API routes now but in a way that wouldn't do anything:

  GlobalConfiguration.Configure(y => y.MapHttpAttributeRoutes(Localization.LocalizationDirectRouteProvider));

  GlobalConfiguration.Configuration.ContinueAfterPreviousInitialization(x => {
    x.Routes.Localization(y => {
      y.AcceptedCultures = new HashSet<String>(new String[] { "en" });
      y.DefaultCulture = "en";
      y.AttributeRouteProcessing = RouteLocalization.Http.Setup.AttributeRouteProcessing.None;
      y.AddCultureAsRoutePrefix = false;
      y.AddTranslationToSimiliarUrls = false;
    }).TranslateInitialAttributeRoutes().Translate(y => {  });
  });

  GlobalConfiguration.Configuration.MessageHandlers.Add(new CultureSensitiveMessageHandler() {
    GetCultureFromHttpRequestMessageDelegate = x => new CultureInfo("en")
  });

  GlobalConfiguration.Configuration.Filters.Add(new CultureSensitiveActionFilterAttribute(true, true));

When I called the Api routes I got 404 errors. I switched to API setup:

  GlobalConfiguration.Configure(x => x.MapHttpAttributeRoutes());

In this case everything works fine ... Any idea what might be wrong?

Thank You,
Miguel

Translation Route '{id:int}/{slug?}' contains different { } placeholders than original Route 'pages/{id}/{slug}'

This is the complete exception:

Translation Route 'sl/strani/{id:int}/{slug?}' contains different { } placeholders than original Route 'pages/{id}/{slug}'.Set Configuration.ValidateURL to false, if you want to skip validation.

The thing is, that's not actually true:

Controller

[RoutePrefix("pages")]
public partial class ContentPageController : BaseController

Action

    [Route("{id:int}/{slug?}")]
    public virtual ActionResult Display(int id, string slug, string culture)

Translated route

        localization.ForCulture("sl")
            .SetRoutePrefix("strani")
            .ForController<ContentPageController>()
            .ForAction(x => x.Display())
            .AddTranslation("{id:int}/{slug?}");

Maybe a bug when using more than 2 cultures?

Hello,

I am using RouteLocalizationMVC experimental branch with MVC 5.0.

It seems there is a problem when using more than 2 cultures.

In HomeController I have the following action with Portuguese as default culture:

[Route("inicio", Name = "home.index"), HttpGet]
public virtual ActionResult Index() { }

The RouteLocalizationMVC configuration is the following:

RouteTable.Routes.Localization(x => {
  x.AcceptedCultures = new HashSet<String>(new List<String> { "pt", "en", "es"});
  x.DefaultCulture = "pt";
  x.RootTranslationProcessing = RootTranslationProcessing.ApplyDefaultCultureToRoute;
  x.AddCultureAsRoutePrefix = true;
}).Translate(x => {
  x.ForCulture("en").ForNamedRoute("home.index").AddTranslation("home");
  x.ForCulture("es").ForNamedRoute("home.index").AddTranslation("inicio");
});

To change culture I have the following code in a view:

@foreach (String culture in new String[] { "pt", "en", "es" }) {
  <a href="@Url.RouteUrl("home.index", new { @culture = culture })">@culture</a>
}

When the site starts the inicial url is, as expected, "pt/inicio" and the three links are rendered as "pt/inicio", "en/home" and "es/inicio". Until now everything is ok ...

When I click "en/home" the culture changes to english but the links become:
"pt/inicio", "en/home", "en/home"

If I would click "es/inicio" instead of "en/home" I would get Spanish version with links:
"pt/inicio", "es/inicio", "es/inicio"

Any idea what might be wrong?

Thank You,
Miguel

Optional arguments issue

We already discussed the optional arguments and your @Dresel solution was to do this:

        localization.ForCulture("sl-si")
            .SetRoutePrefix("objave")
            .ForController<PostsController>()
            .ForAction(x => x.List(0, 0, 0, ""), new Type[] {typeof (int), typeof (int), typeof (int), typeof (string)})
            .AddTranslation("{year}/{month}/{day}");

For the following controller action:

    [Route("list/{year}/{month}/{day}")]
    public virtual ActionResult List(int day = 0, int month = 0, int year = 0, string culture = "")

I just noticed this registers only the route that picks up URLs with complete arguments:

/sl-si/objave/2014/12/23 (content per day 23. 12. 2014)

but not

/sl-si/objave/2014/12 (content per month 12/2014)

or /sl-si/objave/2014 (content per year 2014).

Without using RL the route registration works with all these three options of URLs.

Error: HttpConfiguration.EnsureInitialized() is called in the application's startup code after all other initialization code.

Hello,

I added RouteLocalizationMVC to my application and got a problem. I have:

[Route("signin"), HttpGet]
public virtual ActionResult SignIn() { }

I have an action link on a view and when I click it I am redirected to Sign In view.

Then I added the following RouteLocalizationMVC code:

RouteTable.Routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

RouteTable.Routes.MapMvcAttributeRoutes();
AreaRegistration.RegisterAllAreas();

LocalizationHttpModule.GetCultureFromHttpContextDelegate = context => { return new System.Globalization.CultureInfo("pt"); };

Configuration.AddCultureAsRoutePrefix = true;

RouteTable.Routes.ForCulture("pt").ForController<UserController>().ForAction(y => y.SignIn()).AddTranslation("entrar");

The link as the culture code prefix and it is translated to Portuguese as expected ...

But when I click it I get the following error:

The object has not yet been initialized. Ensure that HttpConfiguration.EnsureInitialized() is called in the application's startup code after all other initialization code.

Note that without the RouteLocalizationMVC I am able to follow the link.

What might be wrong?

Thank You,
Miguel

Culture as a parameter on the routes

As I see it, now you are supposed to add translation using fluent method .ForCulture("de"). This does add the culture identifier but what if we also wanted to use culture as a parameter on our actions?

What I've had for now with conventional routes is something like

"{culture}/pages/list"

which would result in "en/pages/list" or "de/seite/list" but on the action signature I'd also have culture parameter, which I'd then use for filtering to the selected culture.

Now I'm switching over to attribute routing and I could do it simply with [Route("{culture}/list")] but with RouteLocalization in place this would result in duplicated culture identifier.

Do you have a solution for this use case?

403 error when turning AddCultureAsRoutePrefix from false to true

Hello,

I have the following actions on an MVC 5.2 web site with Route Localization:

[Route]
public virtual ActionResult Index() { }

[HttpGet, Route("test")]
public virtual ActionResult Test() { }

On this website I do not want to translate any routes. I want only to add the current culture as prefix.

In the future I will add translations so I want to have everything set up. So I have:

    RouteTable.Routes.MapMvcAttributeRoutes(LocalizationDirectRouteProvider);
    RouteTable.Routes.Localization(x => {
      x.AcceptedCultures = new HashSet<String> { "en" };
      x.DefaultCulture = "en";
      x.AttributeRouteProcessing = AttributeRouteProcessing.AddAsDefaultCultureRoute;
      x.AddCultureAsRoutePrefix = false;
      x.AddTranslationToSimiliarUrls = false;
  }).TranslateInitialAttributeRoutes().Translate(x => {  });

  CultureSensitiveHttpModule.GetCultureFromHttpContextDelegate = context => { return new System.Globalization.CultureInfo("en"); };

  GlobalFilters.Filters.Add(new CultureSensitiveActionFilterAttribute(true, true));

This works fine but I do not get the culture prefix on my routes.

So I turned Add Culture Prefix to true:

   x.AddCultureAsRoutePrefix = true;

And know I get an

HTTP Error 403.14 - Forbidden
The Web server is configured to not list the contents of this directory.

What am I missing?

Thank You,
Miguel

Support for full language + locale culture strings?

I have just picked up this package as we're looking to globalize our MVC application including route URLs. In the example all the localization is done against a simple language string such as "en" or "de", however we use a custom controller factory which sets the CurrentCulture and CurrentUICulture to a fully-localized culture such as "en-GB" or "fr-FR". This seems to break the localized URLs unless when I configure the localization I specify the full culture strings:

const string DefaultCulture = "en-GB";
ISet<string> acceptedCultures = new HashSet<string>() { defaultCulture, "fr-FR" };

However I would have thought that the localization should be able to just pick up the language ("en" or "fr") even when the thread has a full language and locale specified? Is it just doing an exact string match somewhere and if so can this behaviour be modified?

Home page route (root empty route) issues

I'm having constant issues with the root route in my applications. My web apps use both variants of route translation registration (neutral and default) - not both in one app but different across apps.

The issue with default in combination with 'addcultureprefix' setting is that it modifies my Home route - this would be the one that listens at http://domain.com/. RL modifies it to http://domain.com/en.

If I use neutral this doesn't happen but then culture prefixes are gone for all the routes (which I don't want).

What is the best way to tell RL to leave this one route alone or to remove it and bring back the original root route as specified in my controller with attribute routing?

I tried doing this

public static void RemoveDefaultRouteTranslation<T>(this RouteTranslator<T> localization)
{
    var localizationCollectionRoute = localization.GetRoutes().Single();
    localizationCollectionRoute.RemoveTranslation(localization.Configuration.DefaultCulture);
    // localization.AddTranslation("~/");
    }

or with the last line uncommented and it didn't work in any case.

404 when accessing web api

Hello,

I have the following web api action:

[Route("units/get"), HttpGet]
public IHttpActionResult Get() { }

When I use the following I am able to access the api action:

  System.Web.Http.GlobalConfiguration.Configure(x => x.MapHttpAttributeRoutes());

But when I use RouteLocalization I get a 404 error when I try to access the API:

  GlobalConfiguration.Configure(y => y.MapHttpAttributeRoutes(Localization.LocalizationDirectRouteProvider));
  GlobalConfiguration.Configuration.ContinueAfterPreviousInitialization(x => {
    x.Routes.Localization(y => {
      y.AcceptedCultures = new HashSet<String>(new List<String> { "en" });
      y.DefaultCulture = "en";
      y.AttributeRouteProcessing = RouteLocalization.Http.Setup.AttributeRouteProcessing.None;
      y.AddCultureAsRoutePrefix = false;
      y.AddTranslationToSimiliarUrls = false;
    }).TranslateInitialAttributeRoutes();
  });
  GlobalConfiguration.Configuration.MessageHandlers.Add(new RouteLocalization.Http.CultureSensitiveMessageHandler() {
    GetCultureFromHttpRequestMessageDelegate = RouteLocalization.Http.Localization.DetectCultureFromBrowserUserLanguages(new HashSet<String>(new List<String> { "en" }), "en")
  });
  GlobalConfiguration.Configuration.Filters.Add(new RouteLocalization.Http.CultureSensitiveActionFilterAttribute(true, true));

Any idea what might be wrong?

Thank You,
Miguel

AddAsNeutralRouteAndReplaceByFirstTranslation, two cultures, one default

When using AddAsNeutralRouteAndReplaceByFirstTranslation the empty route gets removed within RouteTranslator. This prevents me from having a default empty root atribute route.

My setup is default culture = "en", allowed cultures is "en, sl" and my neutral attribute routes are actually all "en" - that way, by default, if there is only english supported, I don't have to add "en" localizations.

However, I think this removes the empty route from the route table:

        if (Configuration.AttributeRouteProcessing == AttributeRouteProcessing.AddAsNeutralRouteAndReplaceByFirstTranslation)
        {
            // Remove neutral route
            route.RemoveTranslation(string.Empty);
        }

What was the reasoning behind this?

If I comment this out my site works, empty root route loading the correct controller/view.

Named Route not Found in new Version

Hello,

Sorry for the delay on my answers. I was away on a project.
Today I am testing the new version of RouteLocalization.Mvc.

I updated the packages on a project where I have the following on HomeController:

[Route("inicio", Name = "home.index"), HttpGet]
public virtual ActionResult Index() { }

On route translations I have

  localization.ForCulture("en")
    .ForNamedRoute("home.index").AddTranslation("home");:

This was working on previous version but now I get the error:

An exception of type 'System.InvalidOperationException' occurred in RouteLocalization.Mvc.dll but was not handled in user code
Additional information: No Route found for name 'home.index'.

UPDATE

I also have the following:

  localization.ForCulture("en")
    .ForController<PageController>()
      .ForAction(x => x.Company()).AddTranslation("company")

And I got the error:

An exception of type 'System.InvalidOperationException' occurred in RouteLocalization.Mvc.dll but was not handled in user code

Additional information: No Route found for given Controller 'Page' and Action 'Company'.

Everything was working fine on previous version.

I didn't change any code besides adapting the configuration which is now:

  RouteTable.Routes.Localization(x => {
    x.AcceptedCultures = new HashSet<String>(new String[] { "pt", "en" });
    x.DefaultCulture = "pt";
    x.AttributeRouteProcessing = AttributeRouteProcessing.AddAsDefaultCultureRoute;
    x.AddCultureAsRoutePrefix = true;
  }).Translate(x => {
    x.ForCulture("en")
      .ForController<PageController>()
      .ForAction(x => x.Company()).AddTranslation("company")
  });
  CultureSensitiveHttpModule.GetCultureFromHttpContextDelegate = context => { return context.GetCulture(); };

Am I doing some mistake with the new configuration?

Thank You,
Miguel

Problem when adding resolver

With the new version of RouteLocalization I am adding the resolver:

  RouteTable.Routes.MapMvcAttributeRoutes(
    new System.Web.Mvc.Routing.DefaultInlineConstraintResolver().With(r => {
      r.ConstraintMap.Add("notetype", typeof(EnumValueConstraint<NoteType>));
      return r;
    })
  );

With this I get the error:

An exception of type 'System.ArgumentException' occurred in System.Web.dll but was not handled in user code

Additional information: A route named 'home.index' is already in the route collection. Route names must be unique.

I wasn't getting this error with the previous version.

Yes, I do added the name "home.index" to my home/index action.

But this error does not happen if I remove the resolver.

Why?

Culture parameter on controller action in MVC

I've noticed an issue with RL where it picks up neutral route for URL generation when my controller action signature is like this:

    public virtual ActionResult Display(int id, string slug = "", string culture = "")

This happens when using T4MVC for action calls within markup like this:

@Html.ActionLink(@Model.Title, pndng.Posts.Display(Model.Id, Model.Slug))

Even if I explicitly add culture in (most of the time I have it on my viewmodel) like this:

@Html.ActionLink(@Model.Title, pndng.Posts.Display(Model.Id, Model.Slug, Model.Culture))

it still doesn't render out the correct URL for our localized route (which we do have).

Normally you don't have this kind of @Html.ActionLink overload when using pure Razor syntax out-of-the-box. In this case, this is an extension ActionLink method on the Html helper provided by T4MVC. The culture param on my action has a default value as you can see.

Apparently the culture from the thread is not getting injected when server renders the markup for the above T4MVC extension call.

But, everything does work fine if I change my action to this and correct the calls accordingly:

    public virtual ActionResult Display(string culture, int id, string slug = "")

Do you think this is RL issue or T4MVC issue?

How to use RouteLocalization for language prefix only?

I would like to use RouteLocalization for setting culture and generating route URLs with language code prefix, not with localication of entire url. Ie. I want to have the following URLs in the sample:

/en/Welcome
/de/Welcome
/en/Book/1
/de/Book/1

I'm unable to find out how I'm supposed to do that (if it's even possible) and the documentation is very sparse. Is this supported scenario somehow?

Area named added twice to route in version 2.0

Hello,

Were there any changes in AreaPrefix on the version 2.0?

On a project I have the following home controller on an area named "CMS":

[RouteArea("cms", AreaPrefix = "cms")]
public partial class HomeController : WebController {
  [Route("home", Name = "cms.home.index"), HttpGet]
  public virtual ActionResult Index() { }
  }
}

This is a project where I will translate routes soon but for now I do not want to translate them but I would like to have everything ready so my configuration is as follows:

  RouteTable.Routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
  RouteTable.Routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.([iI][cC][oO]|[gG][iI][fF])(/.*)?" });

  DefaultInlineConstraintResolver resolver = new DefaultInlineConstraintResolver();
  resolver.ConstraintMap.Add("loglevel", typeof(EnumValueConstraint<LogLevel>));
  RouteTable.Routes.MapMvcAttributeRoutes(resolver, Localization.LocalizationDirectRouteProvider);

  RouteTable.Routes.Localization(x => {
    x.AcceptedCultures = Settings.I18N.AcceptedLanguages;
    x.DefaultCulture = Settings.I18N.DefaultLanguage;
    x.AttributeRouteProcessing = RouteLocalization.Mvc.Setup.AttributeRouteProcessing.AddAsDefaultCultureRoute;
    x.AddCultureAsRoutePrefix = false;
    x.AddTranslationToSimiliarUrls = false;
  }).TranslateInitialAttributeRoutes().Translate(x => { } );

  CultureSensitiveHttpModule.GetCultureFromHttpContextDelegate = context => { return context.GetCulture(); };
  GlobalFilters.Filters.Add(new CultureSensitiveActionFilterAttribute(true, true));
  RouteTable.Routes.MapRoute("404", "{*url}", new { controller = "Error", action = "NotFound_" });
  AreaRegistration.RegisterAllAreas();

Somehow when I try to access the home view of the cms area the link is:

http://localhost:17963/cms/cms/home

Everything works but I get cms twice on every route of that area.

Am I missing something? With alpha version this was not happening.

Thank You,
Miguel

Error when using Int Constraints and so on ...

Hello,

I have the following route:

[Route("noticias/{id:int}/{slug}"), HttpGet]
public virtual ActionResult Article(Int32 id, String slug) {
}

And I added the following translation:

ForAction(x => x.Article(1, null), new Type[] { typeof(Int32), typeof(String) }).AddTranslation("news/{id:int}/{slug}")

I get the following error:

An exception of type 'System.InvalidOperationException' occurred in RouteLocalizationMVC.dll but was not handled in user code
Additional information: Translation Route 'en/news/{id:int}/{slug}' contains different { } placeholders than original Route 'pt/noticias/{id}/{slug}'.Set Configuration.ValidateURL to false, if you want to skip validation.

I checked and the route in the controller includes the ":int" constraint.
So if I remove the ":int" from both routes then it works fine ...

Is this a problem with my code or something to be fixed?

Thank You,
Miguel

Multiple Routes with different Url found for given Controller 'Account' and Action 'Index'. Narrow down your selection

I'm currently modifying our existing MVC application to use localized routes but am running into an issue with actions that have multiple routes and how to add translations for them. We have the following controller:

[RoutePrefix("Account")]
public class AccountController : BaseController
{
    [Route, Route("Index")]
    public ActionResult Index()
    ...

The index action needs to work via both Account/ and Account/Index to be compatible with the existing application structure. However when adding a localized route:

localization.ForCulture("fr-FR").ForController("Account", "MyApplication.Controllers").SetRoutePrefix("compte").ForAction("Index").AddTranslation("index");

I get the error Multiple Routes with different Url found for given Controller 'Account' and Action 'Index'. Narrow down your selection but I'm not sure how to solve this? Is using named routes the only way?

HttpGet and HttpPost actions

With previous version of RouteLocalization I had:

.ForAction(x => x.Contact()).AddTranslation("contact").AddTranslation("contact")

For the following Routes

[Route("contacto"), HttpGet]
public virtual ActionResult Contact(String s) {
} // Contact

[Route("contacto"), HttpPost]
public virtual ActionResult Contact(PageContactModel model) {
} // Contact

When I ran the project with the new RouteLocalization version I got the error:
Sequence contains more than one matching element

I then tried to use the following:

.ForAction(x => x.Contact(), new Type[] { typeof(String) }).AddTranslation("contact")
.ForAction(x => x.Contact(), new Type[] { typeof(PageContactModel) }).AddTranslation("contact")

But I got the same error. Am I missing something?

Overriding route prefix at controller

With 2.0.0-alpha-6 this worked:

[RoutePrefix("pages")] public partial class ContentPageController : BaseController { [Route("~/{id:int?}/{slug?}", Order=0)] public virtual ActionResult Display(int id = 0, string slug = "", string culture = "")... }

        localization.ForCulture("sl-si")
            .ForController<ContentPageController>()
            .ForAction(x => x.Display(0, "", ""), new Type[] { typeof(Int32), typeof(String), typeof(string) })
            .AddTranslation("{id}/{slug}");

The routes for content pages resulted in

/en/1/welcome
/sl-si/2/...

Now it adds "pages" prefix for all localized routes, results in

/sl-si/pages/2/...

The thing is, pages are special case. They are not denoted by prefix (although it is set at controller level). The route above does not contain any text to localize because of this special (you can think of it as top level routes) case.

I tried adding .SetRoutePrefix("") but didn't help.

Now I could remove the prefix at controller but I don't really want to do that.

How to use Angular with RouteLocalization

Hello,

I have an ASP.NET MVC / Web API application where each page is a SPA using Angular.

Each page can have multiple sections being each one a partial view as described here:
http://www.wintellect.com/devcenter/dbaskin/angularjs-mvc-cookbook-simple-routing

Consider the following route in Angular:

    $routeProvider.when('/About', {
        templateUrl: '/Home/About',
        controller: 'aboutCtrl',
    });

Link "/About" loads calls MVC's "/Home/About" that returns a partial view where aboutCtrl is used.

However RoutesLocalization changes routes depending on culture ... So this won't work ...

My idea would be a GlobalFilter that loads all Routes (MVC and API) into a dictionary:

Dictionary<String, String> routes = new Dictionary<String, String> {
  { "Route1Key", "/en/about" },
  { "Route2Key", "en/contact" }
};

Then transform this in JSON and put it in a global variable using window.routes = ...
Then in angular routing use the keys on that dictionary to define routes.

Or instead of a filter I could simply this do on the master view ... Or ViewStart?
Can I have the keys for those routes? Should I name every route?

Did anyone ever used Angular with RouteLocalization in such a way?

Thank You,
Miguel

Add translation to GET and POST routes with Int and String parameters

Hello,

I am having a few problems to translate the following two routes:

[Route("documents"), HttpGet]
public virtual ActionResult Documents(Int32 page = 1)  { }

[Route("documents"), HttpPost]
public virtual ActionResult Documents(String query, Int32 page = 1)  { }

Basically the first route gets a paged list of documents, using page = 1 when not specified. And the second also accepts a string query to filter the documents.

So for translation I am using the following:

.ForAction(x => x.Documents(), new Type[] { typeof(Int32) }).AddTranslation("documentos")
.ForAction(x => x.Documents(), new Type[] { typeof(String), typeof(Int32) }).AddTranslation("documentos")

But I get the errors:
An expression tree may not contain a call or invocation that uses optional arguments
An expression tree may not contain a call or invocation that uses optional arguments

I tried a few variations of this but I always get an error.

Any idea what might be wrong?

Thank You,
Miguel

Route name, start culture and current culture constraint.

I am using the following route localization configuration:

Configuration.AcceptedCultures.Add("en");
Configuration.AcceptedCultures.Add("pt");
Configuration.DefaultCulture = "pt";      
Configuration.ApplyDefaultCultureToRootRoute = true;
Configuration.AddCultureAsRoutePrefix = true;

routes.ForCulture("en").ForController<HomeController>().ForAction(y => y.Index()).AddTranslation("home");
routes.ForCulture("en").ForController<UserController>().ForAction(y => y.SignIn()).AddTranslation("signin");
routes.ForCulture("pt").ForController<HomeController>().ForAction(y => y.Index()).AddTranslation("inicio");
routes.ForCulture("pt").ForController<UserController>().ForAction(y => y.SignIn()).AddTranslation("entrar");

LocalizationHttpModule.GetCultureFromHttpContextDelegate = context => {
  return new CultureInfo(Configuration.DefaultCulture);      
};  

The controllers are:

public partial class HomeController : Controller {

[Route("home", Name = "home"), HttpGet]
public virtual ActionResult Index() {
  return View();
} // Index

[Route, HttpGet]
public virtual ActionResult Start() {
  return RedirectToAction(MVC.Home.Index());
} // Start

} // HomeController

public partial class UserController : Controller {

[Route("signin"), HttpGet]
public virtual ActionResult SignIn() {
  // Code
} // SignIn

[Route("signin"), HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult SignIn(UserSignInModel model) {
  // Code
} // SignIn

}

The Problems

  1. It seems RouteLocalization is not preserving the Route Names.
    Despite of Home route having the name "home" the following route is not found:

    <a href="@Url.RouteUrl("home", new { @culture = culture })">

  2. When I start the site I always get the English version.
    Note that it should be, I think, PT since the default culture is PT:

    LocalizationHttpModule.GetCultureFromHttpContextDelegate = context => {
    return new CultureInfo(Configuration.DefaultCulture);
    };

  3. When I change culture to "PT" I am able to access: "/pt/signin". Why?
    This shouldn't happen ... It should exist only "pt/entrar" and "en/signin"

    Somehow with the post configuration I get the following routes:
    signin, pt/signin, pt/entrar, and en/signin

    Why the first two?

Thank You,
Miguel

Route Translation of Optional Parameters - The route URL cannot start ...

Hello,

I have the following route:

[Route("noticias/{type?}"), HttpGet]
public virtual ActionResult News(Int32 p = 1, String type = null) {
}

And I added the following translation:

ForAction(x => x.News(1, null)).AddTranslation("news/{type?}")

But I get the following error:

An exception of type 'System.ArgumentException' occurred in System.Web.dll but was not handled in user code

Additional information: The route URL cannot start with a '/' or '~' character and it cannot contain a '?' character.    

Is there a way to solve this using the current RouteLocalizationMVC version?

Thank You,
Miguel

Culture in Route and Other Options to Detect Culture

Hello,

I was looking at the code and trying the RouteLocalizationMVC.WebSample ...

Like you I have been using AR for quite sometime with Localization ...
In fact it was me that first suggested adding localization to AR.

May I make a few suggestions and as a few questions?

  1. How would you add the culture to the route?
    One of good thing in AR is that you would get routes like:
    /en/book/2/10 or /de/buch/2/10
    This is good for SEO and provides other ways to change culture.

  2. You use a LocalizationHttpModule to define the culture from HttpHeader.
    Could you add other options or make it more plugable in configuration?
    Let me two common examples to initially define the culture:

    2.1. Cookie.
    Sometimes saving the preference in a cookie is a good option;

    2.2. Domain
    In a few projects I often used the domain to define the culture.
    For example, if the user accesses the site through "mydomain.com" I would define the culture as "en" if the request came from "mydomain.de" I would define the initial culture as "de".

    In fact having one TLC for each culture is the recommended even if sometimes is not so easy to get the domains.

    I usually use HttpContext.Current.Request.Url.Host to define that ...

    So this why I wrote that something more plugable would be nice.

What do you think?

Thank You,
Miguel

RouteLocalizationMVC integration with I18N

Hello Dresel,

I would like to use RouteLocalizationMVC with I18N project.

My objective is to somehow do not duplicate the code to define and change the culture in the web site.

While discussing this in I18N project the following question was made:

Ideally here you would add a custom handler that calls a RouteLocalizationMVC API passing langtag.GetCultureInfo(). Can you find out if they support such an API?

Does RouteLocalizationMVC has that API?

This is the full text of it:

By the looks of it, the RouteLocalizationMVC module needs to be handed a cultureinfo on each request for it to do its thing. It looks like they allow you to provide the logic for that via the LocalizationHttpModule.GetCultureFromHttpContextDelegate hook. Thus, they are not 'setting' the culture, but getting it. There shouldn't be a clash with i18n therefore.

i18n does the following with respect to language determination:

The i18n.LocalizingModule hooks the BeginRequest ASP.NET pipeline event.
The handler for that event looks at the URL, cookies and language headers to determine a language setting for the request (PAL).
It then calls the registered i18n.LocalizedApplication.SetPrincipalAppLanguageForRequestHandlers handlers with that language tag. The default handler does this:

Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = langtag.GetCultureInfo();

although you can augment this or override it.

Ideally here you would add a custom handler that calls a RouteLocalizationMVC API passing langtag.GetCultureInfo(). Can you find out if they support such an API?

If they don't, then you can override their LocalizationHttpModule.GetCultureFromHttpContextDelegate method like this:

LocalizationHttpModule.GetCultureFromHttpContextDelegate = httpContext =>
{
return httpContext.GetPrincipalAppLanguageForRequest().GetCultureInfo();
};

although that will only work if they call LocalizationHttpModule.GetCultureFromHttpContextDelegate AFTER the i18n BeginRequest event handler is called. By the looks of it they are also an HttpModule so that will be down to the pipeline events they are handling and/or possibly the order the modules are registered.

Thank You,
Miguel

Unit testability of Localization

I started creating an attribute-based translation system on top of our controllers, but I'm unable to have it unit tested because the classes are not abstracted with interfaces or abstract classes. It would be great to be able to mock or fake the localization classes, including the RouteTranslator objects.

Start Action not Working with new version

Hello,

I think something is going wrong with the new version of Route Localization.

On the HomeController I have the following:

[Route("inicio", Name = "home.index"), HttpGet]
public virtual ActionResult Index() {
  return View();
} // Index

[Route, HttpGet]
public virtual ActionResult Start() {
  return RedirectToAction(MVC.Home.Index());
} // Start

So when the application starts I redirect www.domain.com to:

www.domain.com/en/home

or

www.domain.com/pt/inicio

As soon as I start the project I get a 404 error.

I placed a breakpoin int Start action and it never fires.

After getting the 404 error I can navigate to other actions including the homepages in two different cultures ... But I always get the 404 error.

Any idea what might be going on?

Maybe this is also the cause of my other error?

Thank You,

3 Routes Are Generated for 2 Languages

Hello,

I have the following Routes:

public partial class PageController : WebController {
  [Route("contacto"), HttpGet]
  public virtual ActionResult Contact() { }
  [Route("contacto"), HttpPost]
  public virtual ActionResult Contact(PageContactModel model) { }
}

And the following configuration:

  RouteTable.Routes.Localization(x => {
    x.AcceptedCultures = new HashSet<String>(new List<String> { "pt", "en" });
    x.DefaultCulture = "pt";
    x.RootTranslationProcessing = RootTranslationProcessing.ApplyDefaultCultureToRoute;
    x.AddCultureAsRoutePrefix = false;
  }).Translate(x => {
    x.ForCulture("en")
      .ForController<PageController>()
        .ForAction(y => y.Contact()).AddTranslation("contact")
        .ForAction(y => y.Contact(), new Type[] { typeof(PageContactModel) }).AddTranslation("contact");
  });

When I run the code I get the error:

An exception of type 'System.InvalidOperationException' occurred in RouteLocalizationMVC.dll but was not handled in user code
Additional information: No Route found for given Controller 'Page' and Action 'Contact'.

The site runs if I remove the HttpPost Contact translation. But, using Glimpse, I get 3 routes: "pt/contacto", "en/contact" and "contacto"

The Action Links generate "pt/contacto" and "en/contact" but when I click them I get a 404 error. If I access the route "contacto" I am able to see the page.

"contacto" route shouldn't even exist, correct?

Please, does anyone knows what is wrong?

Thank You,
Miguel

Error when there are controllers with same name in different part of the project

Hello,

I think I found a bug when a project contains controllers with the same name.

I have the following controller on project root:

namespace MvcSite.Controllers {

  public partial class UserController : Controller {

    [Route("signin"), HttpGet]
    public virtual ActionResult SignIn() { }

    [Route("user/edit"), HttpGet]
    public virtual ActionResult Edit() { }

  }
}

Then I added the RouteLocalizationMvc translations. For example:

  RouteTable.Routes
    .ForCulture("en")
      .ForController<MvcSite.Controllers.UserController>()
        .ForAction(x => x.SignIn()).AddTranslation("signin")
        .ForAction(x => x.Edit()).AddTranslation("user/edit");

When I run it I get the following error:

An exception of type 'System.InvalidOperationException' occurred in RouteLocalizationMVC.dll but was not handled in user code

Additional information: Translation Route 'user/edit' contains different number of { } placeholders than original Route 'cms/access/users/{identifier}/edit'.Set Configuration.ValidateURL to false, if you want to skip validation.

I looked at 'cms/access/users/{identifier}/edit' and realized that I have that route ...
... but in another UserController controller inside an area named CMS:

namespace MvcSite.Areas.CMS.Controllers {

  [RouteArea("cms", AreaPrefix = "cms"), RoutePrefix("access")]
  public partial class UserController : Controller {

    [Route("users/{identifier:guid}/edit"), HttpGet]
    public virtual ActionResult Edit(Guid identifier) {}

  }
}

This might be a bug ... No?

Thank You,
Miguel

Add more fine-grained RoutePrefix control

From issue 48:

Atm when AddCultureAsRoutePrefix is used, the prefix is always added at the beginning of the route. This should be configurable:

Before [RouteArea], [RoutePrefix], [Route] - (as it is now)
After [RouteArea] but before [RoutePrefix], [Route]
After [RouteArea], [RoutePrefix] but before [Route]
After [RouteArea], [RoutePrefix], [Route]

Asp.Net VNext

Hello,

Is RouteLocalization already compatible with Asp.Net VNext?

Thank You,
Miguel

RouteLocalization and Owin

I am using RouteLocalization in MVC 5.2 and I have the following OWIN setup

[assembly: OwinStartup(typeof(Greenbelieve.Site.OwinStartup), "Configure")]

  public partial class OwinStartup {

    public void Configure(IAppBuilder application) {

      UrlHelper url = new UrlHelper(HttpContext.Current.Request.RequestContext);

      application.UseCookieAuthentication(new CookieAuthenticationOptions {
        LoginPath = new PathString(url.Action(MVC.User.SignIn())),
        ...
      });
    ....

When I access a route to which I do not have permission I get the 401 error instead of being redirected to MVC.User.Sign ...

I think this is because of Route Localization and Owin running before RouteLocalization accesses the Route Table.

Is there a way to solve this?

An expression tree may not contain a call or invocation that uses optional arguments

If our actions use optional parameters the above exception occurs when trying to register routes fluently:

        localization.ForCulture("sl")
            .SetRoutePrefix("strani")
            .ForController<ContentPageController>()
            .ForAction(x => x.Display())
            .AddTranslation("{id:int}/{slug?}");

For this action:

    [Route("{id:int}/{slug?}")]
    public virtual ActionResult Display(int id = 0, string slug = "", string culture = "")

Neutral Translation allowing access trough default culture

Hello,

I have the following MVC Route:

[Route("admin/tags"), HttpGet]
public virtual ActionResult Admin() { }

I want this route to be neutral, I mean, not translated and without prefix.

The route localization configuration I have is the following:

RouteTable.Routes.MapMvcAttributeRoutes(Localization.LocalizationDirectRouteProvider);

RouteTable.Routes.Localization(x => {
    x.AcceptedCultures = new HashSet<String>(new String[] { "en", "pt" });
    x.DefaultCulture = "en";
    x.AttributeRouteProcessing = AttributeRouteProcessing.AddAsDefaultCultureRoute;
    x.AddCultureAsRoutePrefix = true;
    x.AddTranslationToSimiliarUrls = true;
  }).TranslateInitialAttributeRoutes().Translate(z => z.Process());

  CultureSensitiveHttpModule.GetCultureFromHttpContextDelegate = ctx => new CultureInfo("en");

 GlobalFilters.Filters.Add(new CultureSensitiveActionFilterAttribute(true, true));

 RouteTable.Routes.MapRoute("Start", String.Empty, new { controller = "Home", action = "Start" }, new[] { "MVCSite.Controllers"" });

And in process extension method I have the following:

public static void Process(this Localization localization) {
  localization.ForCulture("pt")
    .ForNamedRoute("home.index").AddTranslation("inicio");
  localization.ForController<TagController>().ForAction(x => x.Admin()).AddNeutralTranslation();       
} // Process

With this I am able to access:
/admin/tags
/en/admin/tags

And not able to access
/pt/admin/tags

However, I shouldn't be able to access
/en/admin/tags

Only: /admin/tags

No? Am I missing something?

And is there any action attribute to make a route not translated and stay as it is independent of the culture use? I was looking trough the source but didn't find anything.

Thank You

UPDATE from MVC 5.0 to MVC 5.1.2 originate error: multiple types were found that match the controller named 'Home'.

Hello,

I had a RouteLocalizationMVC code working with MVC 5.0.

I updated to MVC 5.1.2 and now I get an error which I am not able to solve.

NOTE: I am using the experimental branch with RootTranslationProcessing which was working.

I have the following RouteLocalization setup:

  RouteTable.Routes.Localization(x => {
    x.AcceptedCultures = new HashSet<String>(new List<String> { "pt", "en", "es"});
    x.DefaultCulture = "pt";
    x.RootTranslationProcessing = RootTranslationProcessing.ApplyDefaultCultureToRoute;
    x.AddCultureAsRoutePrefix = true;
  }).Translate(x => {
    x.ForCulture("en").ForNamedRoute("home.index").AddTranslation("home");
  });

And I have two HomeControllers but in different namespaces:

namespace MVC.Site.Controllers {
  public partial class HomeController : Controller {
    [Route("inicio", Name = "home.index"), HttpGet]
    public virtual ActionResult Index() {}
  }
}

namespace MVC.Site.Areas.CMS.Controllers {
  public partial class HomeController : Controller {
    [Route("inicio"), HttpGet]
    public virtual ActionResult Index() { }
  }
}

When I start the site I get the following error:

Multiple types were found that match the controller named 'Home'. This can happen if the route that services this request ('pt/inicio') does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter.

The request for 'Home' has found the following matching controllers:
MVC.Site.Areas.CMS.Controllers.HomeController
MVC.Site.Controllers.HomeController

NOTE
To change from culture to culture I have on a view:

<a href="@Url.RouteUrl("home.index", new { @culture = pt })">PT</a>
<a href="@Url.RouteUrl("home.index", new { @culture = en })">EN</a>
<a href="@Url.RouteUrl("home.index", new { @culture = es })">ES</a>

Any idea what I might be missing?

Thank You,
Miguel

Change culture parameter name

Hello,

If I am not wrong the parameter that holds the current culture is "culture", right?

Is it possible to change the name of this parameter?

Thank You,
Miguel

Owin redirect problem on latest RL version

Hello,

This is a recurrent problem but it seems there are problems with Owin.

I have the following Owing configuration as I had before:

//LoginPath = new PathString(url.Action(MVC.User.Login())),
Provider = new CookieAuthenticationProvider() {
    OnApplyRedirect = 
        context => context.Response.Redirect(
            url.Action(MVC.User.Login().AddRouteValues(
               new { culture =   Thread.CurrentThread.CurrentCulture.Name })))
     } 

When I try to access a action that requires authentication I get a 401 error.

I have the following Route Localization configuration:

  RouteTable.Routes.MapMvcAttributeRoutes(Localization.LocalizationDirectRouteProvider);
  RouteTable.Routes.Localization(x => {
    x.AcceptedCultures = Settings.I18N.AcceptedLanguages;
    x.DefaultCulture = Settings.I18N.DefaultLanguage;
    x.AttributeRouteProcessing = RouteLocalization.Mvc.Setup.AttributeRouteProcessing.AddAsDefaultCultureRoute;
    x.AddCultureAsRoutePrefix = false;
    x.AddTranslationToSimiliarUrls = false;
  }).TranslateInitialAttributeRoutes().Translate(x => { x.Process(); });
  CultureSensitiveHttpModule.GetCultureFromHttpContextDelegate = context => { return context.GetCulture(); };
  GlobalFilters.Filters.Add(new CultureSensitiveActionFilterAttribute(true, true));

I also changed:

    OnApplyRedirect = 
        context => context.Response.Redirect(
            url.Action(MVC.User.Login().AddRouteValues(
               new { culture =   Thread.CurrentThread.CurrentCulture.Name })))
     } 

To:

    OnApplyRedirect = context => context.Response.Redirect(url.Action(MVC.User.Login())

As I am not setting a route prefix. But the problem remains ...

If I remove RouteLocalization, comment Provider and Uncomment LoginPath and simply use RouteTable.Routes.MapMvcAttributeRoutes() then everything works fine.

Am I missing something, did something change on latest version or is this something related with my RouteLocalization configuration?

Thank You,
Miguel

Split the Web API parts to separate classes

Hey Dresel, would you mind if we split the Web API code parts to separate files instead of having conditional directives (#if, #endif)?

More than that, Web API localized routes make much less sense because in general you'd have one API which would be, in most cases, RESTful and English based and would server content for all cultures/locales using culture parameter which mostly won't be part of a route itself but provided as a querystring parameter. What do you think?

Allow absolute / overriden url localizations

Attribute Routes can be defined absolute / overriden at action level:

[Route("~/Welcome")]
public ActionResult Index()

This should also be possible for localizations and should not add any route prefixes:

localization.AddTranslation("~/Willkommen")

Multiple Routes found for given Controller and Action. Narrow down your selection or use AddTranslationToSimiliarUrls if you want to translate similiar Routes at once.

After upgrading to v.2.1.0 I am now getting this exception for apparent no reason:

Multiple Routes found for given Controller 'Directory' and Action 'List'. Narrow down your selection or use AddTranslationToSimiliarUrls if you want to translate similiar Routes at once.

If I set the AddTranslationToSimiliarUrls to true in configuration, it just results in another exception:

Multiple Routes with different Url found for given Controller 'Directory' and Action 'List'. Narrow down your selection.

The issue could be connected to the fact I use T4MVC in my projects, which adds additional parameterless routes to routes that have parameters.

However, this issue was not present in 2.0.0-alpha-6

How to setup two languages with support for no language provided?

Hi,

First of all, thanks for this great library which seems very powerful. But I am not sure how to setup this scenario:

I wish to support two languages: Danish (da) and English (en).
I wish to have the "/" of my websites language be determent by the browser user language.
I wish to have "/da/" returning the Danish culture and "/en/" returning the english culture.

My problem with the setup below is that "/" is determent by the browser user language (great!) and I can access the site on "/en/" which turns the resources to English (great!) - but I can not access the site on /da/ which just returns 404?

I need this for SEO purpose, as I wish to provide these tags to google:

 <link rel="alternate" href="http://www.mywebsite.com/en/" hreflang="en" /> 
 <link rel="alternate" href="http://www.mywebsite.com/da/" hreflang="da" /> 
 <link rel="alternate" href="http://www.mywebsite.com/" hreflang="x-default" /> 

At the moment my setup is:

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.LowercaseUrls = true;
            routes.AppendTrailingSlash = true;
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapMvcAttributeRoutes(Localization.LocalizationDirectRouteProvider);

            const string defaultCulture = "en";
            ISet<string> acceptedCultures = new HashSet<string> { defaultCulture, "da" };

            routes.Localization(configuration => {
                configuration.DefaultCulture = defaultCulture;
                configuration.AcceptedCultures = acceptedCultures;
                configuration.AttributeRouteProcessing = AttributeRouteProcessing.AddAsNeutralAndDefaultCultureRoute;
                configuration.AddCultureAsRoutePrefix = true;
            }).Translate(localization =>
            {
                localization.TranslateInitialAttributeRoutes();
            });

            CultureSensitiveHttpModule.GetCultureFromHttpContextDelegate = Localization.DetectCultureFromBrowserUserLanguages(acceptedCultures, defaultCulture);
        }

And this filter:

        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
            filters.Add(new CultureSensitiveActionFilterAttribute());
        }

With this controller:

    public class HomeController : Controller
    {
        [Route]
        public ActionResult Index()
        {
            var model = new IndexViewModel
            {
                SendContactEmailCommand = new SendContactEmail()
            };

            return View(model);
        }
    }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.