Pracuję z klientem, który chce, aby adresy URL w naszej aplikacji internetowej były w języku francuskim. Jestem angielskim programistą i mamy również klientów z Polski. Jest to interesujący problem, ale nie sądzę, aby jego działanie wspierało środowisko ASP.NET MVC.Czy można zlokalizować URL/routing w ASP.NET MVC?
Oto scenariusz. Trasa ...
konkretnym przykładzie
English URL
www.stackoverflow.com/questions/ask
będzie również wspierać
francuski URL
www.stackoverflow.com/problème/poser
Ogólny PRZYKŁAD
English URL
http://clientA.product.com/AreaNameEnglish/ControllerNameEnglish/ActionNameEnglish/params
musi również obsługiwać
francuski Adres
http://clientB.product.com/AreaNameFrench/ControllerNameFrench/ActionNameFrench/params
Więc w mojej okolicy MVC, kontroler i wszystkie działania muszą mieć po angielsku i tłumaczenia Francuski.
Oczywiście łatwość konserwacji byłaby ogromnym problemem, gdybym poszedł i zakodował wszystkie moje kontrolery, widoki i nazwy akcji na francuski. Czy istnieje sposób, aby zlokalizować trasę, która jest prezentowana w przeglądarce, nie robiąc tego? Pamiętaj, że w aplikacji jest wiele różnych tras. Kilka obszarów, z których każdy ma garstkę kontrolera, z których każdy ma wiele akcji?
Dzięki,
Justin
EDIT
Dzięki @womp tutaj jest to, co mam wymyślić tak daleko ... Chociaż w końcu wziąłem podejście, które napisałem w odpowiedzi .
public class LocalizedControllerFactory : DefaultControllerFactory
{
public override IController CreateController(RequestContext requestContext, string controllerName)
{
if (string.IsNullOrEmpty(controllerName))
throw new ArgumentNullException("controllerName");
if (CultureInfo.CurrentCulture.TwoLetterISOLanguageName == "fr")
{
controllerName = this.ReplaceControllerName(requestContext, controllerName);
this.ReplaceActionName(requestContext);
this.ReplaceAreaName(requestContext);
}
return base.CreateController(requestContext, controllerName);
}
private string ReplaceControllerName(RequestContext requestContext, string controllerName)
{
// would use the language above to pick the propery controllerMapper. For now just have french
Dictionary<string, string> controllerMapper = new Dictionary<string, string>()
{
{"frenchControllerA", "englishControllerA"},
{"frenchControllerB", "englishControllerB"}
};
return this.ReplaceRouteValue(requestContext, "controller", controllerMapper);
}
private void ReplaceAreaName(RequestContext requestContext)
{
// would use the language above to pick the propery areaMapper. For now just have french
Dictionary<string, string> areaMapper = new Dictionary<string, string>()
{
{"frenchAreaX", "englishAreaX"},
{"frenchAreaY", "englishAreaY"}
};
this.ReplaceRouteValue(requestContext, "area", areaMapper);
}
private void ReplaceActionName(RequestContext requestContext)
{
// would use the language above to pick the propery actionMapper. For now just have french
Dictionary<string, string> actionMapper = new Dictionary<string, string>()
{
{"frenchAction1", "englishAction1"},
{"frenchAction2", "englishAction2"}
};
this.ReplaceRouteValue(requestContext, "action", actionMapper);
}
private string ReplaceRouteValue(RequestContext requestContext, string paramName, Dictionary<string, string> translationLookup)
{
if (requestContext.RouteData.Values[paramName] == null)
{
return null;
}
string srcRouteValue = requestContext.RouteData.Values[paramName] as string;
if (srcRouteValue != null && translationLookup.ContainsKey(srcRouteValue))
{
requestContext.RouteData.Values[paramName] = translationLookup[srcRouteValue];
}
return requestContext.RouteData.Values[paramName] as string;
}
}
Przyzwoity początek. Jeśli zlokalizuję tylko nazwę ControllerName i ActionName w Url, odnajdzie on i wyrenderuje odpowiedni widok. Mam jednak następujące problemy.
Obszar Nazwa nie może być tłumaczone
zlokalizowaniu oznacza metodę Controller.View() nie znajdzie Widoki. Mimo że nazwa obszaru została zastąpiona w kontekście żądania, metoda ViewEngineCollection.Find() nie wydaje się go podnosić. W dowolnym miejscu w klasie kontrolera, która "zwraca widok()", nie można znaleźć domyślnego widoku dla jego działania. Jeśli nie zlokalizuję obszaru, pozostałe kroki będą działać.
RedirectToAction lub Html.ActionLink
Anytime aplikacja wywołuje RedirectToAction lub jeśli używam pomocnika Html.ActionLink lub coś podobnego generowania adresów URL są te angielskie. Wygląda na to, że będę musiał dodać logikę gdzieś możliwie w wielu miejscach, aby przekształcić angielski URL na francuski (lub inny język).
Miłe znalezisko. Jest to zasadniczo ta sama koncepcja, z wyjątkiem zamkniętego w routingu, a nie w logice instancji kontrolera. Zgadzam się, jest to prawdopodobnie nieco bardziej eleganckie, wydaje się, że jest to bardziej odpowiednia domena dla rozwiązania. – womp
Wiem, że to stary post, ale ludzie właśnie uratowali moją skórę. Świetna odpowiedź! –