public static Route MapLocalizedRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces) { if (routes == null) { throw new ArgumentNullException("routes"); } if (url == null) { throw new ArgumentNullException("url"); } var route = new LocalizedRoute(url, new MvcRouteHandler()) { Defaults = new RouteValueDictionary(defaults), Constraints = new RouteValueDictionary(constraints), DataTokens = new RouteValueDictionary() }; if ((namespaces != null) && (namespaces.Length > 0)) { route.DataTokens["Namespaces"] = namespaces; } routes.Add(name, route); return route; }
public static IEnumerable<LocalizedRoute> GetLocalizedRoutes(this RouteCollection routes) { foreach (var item in routes) { if (item is Route) { var localizedRoute = new LocalizedRoute(item as Route); if (localizedRoute.Language != null) { yield return localizedRoute; } } } yield break; }
/// <summary> /// Localizes all convention-based routes in the <paramref name="routeCollection"/> with a custom configured /// <see cref="LocalizationOptions"/> instance. This method should be called after all routes have been configured. /// </summary> /// <param name="routeCollection">The collection containing all the routes of the ASP.NET MVC application.</param> /// <param name="options">A callback to configure the default <see cref="LocalizationOptions"/> instance.</param> /// <exception cref="ArgumentException"><paramref name="routeCollection"/> is null.</exception> public static void Localize(this RouteCollection routeCollection, Action <LocalizationOptions> options) { if (routeCollection == null) { throw new ArgumentNullException(nameof(routeCollection)); } // Create and initialize a new LocalizationOptions instance var localizationOptions = new LocalizationOptions(); options?.Invoke(localizationOptions); localizationOptions.Dictionary.Init(localizationOptions.MvcTopologyProvider); // Create separate collection for all named and unnamed routes var namedMap = typeof(RouteCollection).GetField("_namedMap", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(routeCollection) as Dictionary <string, RouteBase> ?? throw new InvalidOperationException($"There is no _namedMap field in the {nameof(RouteCollection)} class."); var unnamedRoutes = routeCollection.Except(namedMap.Values); // And combine them to a common list with their nullable names as key var routes = namedMap.Concat(unnamedRoutes.Select(route => new KeyValuePair <string, RouteBase>(null, route))).ToList(); // Iterate through all available routes foreach (var routeItem in routes) { // Which has the type Route if ((routeItem.Value is Route route) && (route.GetType() == typeof(Route))) { // Create a new LocalizedRoute proxy string routeName = routeItem.Key; var localizedRoute = new LocalizedRoute(route, localizationOptions.Dictionary); // Replace the original route with this new one int index = routeCollection.IndexOf(route); routeCollection[index] = localizedRoute; if (!string.IsNullOrEmpty(routeName)) { namedMap[routeName] = localizedRoute; } } } }
/// <summary> /// Creates localized routes /// You can override this method to change the source of localized routes - DB, File,... /// </summary> /// <returns>Localized routes</returns> protected virtual async Task <IEnumerable <LocalizedRoute> > GetRoutesAsync() { /* * * LocalizedRouteController - LocalizedRouteAction * LocalizedRouteController - RouteAction * LocalizedRouteController - OriginalAction * RouteController - LocalizedRouteAction * OriginalController - LocalizedRouteAction * */ var localizedRoutes = new List <LocalizedRoute>(); foreach (var routeDescriptor in _controllerActionDescriptorProvider.Get()) { routeDescriptor.RouteValues.TryGetValue("controller", out var controller); routeDescriptor.RouteValues.TryGetValue("action", out var action); var controllerLocalizedRouteAttributes = GetControllersAttribute <LocalizedRouteAttribute>(routeDescriptor); var controllerRouteAttributes = GetControllersAttribute <RouteAttribute>(routeDescriptor); var actionLocalizedRouteAttributes = GetMethodsAttribute <LocalizedRouteAttribute>(routeDescriptor); var actionRouteAttributes = GetMethodsAttribute <RouteAttribute>(routeDescriptor); foreach (var controllerLocalizedRouteAttribute in controllerLocalizedRouteAttributes) { var actionLocalizedRouteAttribute = actionLocalizedRouteAttributes .FirstOrDefault(s => s.Culture == controllerLocalizedRouteAttribute.Culture); if (actionLocalizedRouteAttribute != null) { AddLocalizedRoute(controllerLocalizedRouteAttribute.Culture, controllerLocalizedRouteAttribute.Template, actionLocalizedRouteAttribute.Template); } else if (actionRouteAttributes.Any()) { foreach (var actionRouteAttribute in actionRouteAttributes) { AddLocalizedRoute(controllerLocalizedRouteAttribute.Culture, controllerLocalizedRouteAttribute.Template, actionRouteAttribute.Template); } } else { AddLocalizedRoute(controllerLocalizedRouteAttribute.Culture, controllerLocalizedRouteAttribute.Template, action); } } foreach (var controllerRouteAttribute in controllerRouteAttributes) { foreach (var actionLocalizedRouteAttribute in actionLocalizedRouteAttributes) { AddLocalizedRoute(actionLocalizedRouteAttribute.Culture, controllerRouteAttribute.Template, actionLocalizedRouteAttribute.Template); } foreach (var actionRouteAttribute in actionRouteAttributes) { foreach (var culture in _supportedCultures) { AddLocalizedRoute(culture.Name, controllerRouteAttribute.Template, actionRouteAttribute.Template); } } if (!actionRouteAttributes.Any() && !actionLocalizedRouteAttributes.Any()) { foreach (var culture in _supportedCultures) { AddLocalizedRoute(culture.Name, controllerRouteAttribute.Template, action); } } } if (!controllerLocalizedRouteAttributes.Any() && !controllerRouteAttributes.Any()) { foreach (var actionLocalizedRouteAttribute in actionLocalizedRouteAttributes) { AddLocalizedRoute(actionLocalizedRouteAttribute.Culture, controller, actionLocalizedRouteAttribute.Template); } foreach (var actionRouteAttribute in actionRouteAttributes) { foreach (var culture in _supportedCultures) { AddLocalizedRoute(culture.Name, controller, actionRouteAttribute.Template); } } if (!actionLocalizedRouteAttributes.Any() && !actionRouteAttributes.Any()) { foreach (var culture in _supportedCultures) { AddLocalizedRoute(culture.Name, controller, action); } } } void AddLocalizedRoute(string cultureName, string controllerName, string actionName) { localizedRoutes.Add(LocalizedRoute.Create(cultureName, RouteInformation.Create(controller, action), RouteInformation.Create(controllerName, actionName))); } } return(localizedRoutes); }