Comments (6)
I can't reproduce this.
I have used your setup from your previous issue:
// Configure localization
services.AddSingleton(provider =>
{
RequestLocalizationOptions requestLocalizationOptions = new RequestLocalizationOptions()
{
DefaultRequestCulture = new RequestCulture("en"),
// Formatting numbers, dates, etc.
SupportedCultures = new[] { new CultureInfo("en"), new CultureInfo("pt") },
// UI strings that we have localized.
SupportedUICultures = new[] { new CultureInfo("en"), new CultureInfo("pt") },
};
// Replaces CultureSensitiveActionFilterAttribute
requestLocalizationOptions.RequestCultureProviders.Insert(0, new RouteDataRequestCultureProvider());
return requestLocalizationOptions;
});
// Add framework services.
services
.AddMvc(x => { x.Filters.Add(new MiddlewareFilterAttribute(typeof(LocalizationPipeline))); })
.AddRouteLocalization(x =>
{
x.UseCulture("en")
.WhereUntranslated()
.AddDefaultTranslation();
x.UseCulture("pt")
.WhereController(nameof(HomeController))
.WhereAction(nameof(HomeController.Index))
.TranslateAction("");
x.UseCulture("pt")
.WhereController(nameof(AboutController))
.WhereAction(nameof(AboutController.Index))
.TranslateAction("quem-somos");
})
.AddTypedRouting()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization();
services.AddSingleton(x => {
RequestLocalizationOptions requestLocalizationOptions = new RequestLocalizationOptions()
{
DefaultRequestCulture = new RequestCulture("en"),
SupportedCultures = new[] { new CultureInfo("en"), new CultureInfo("pt") },
SupportedUICultures = new[] { new CultureInfo("en"), new CultureInfo("pt") },
};
requestLocalizationOptions.RequestCultureProviders.Insert(0, new RouteDataRequestCultureProvider());
return requestLocalizationOptions;
});
services.Configure<MvcOptions>(options => options.Conventions.Add(new CollectRoutesApplicationConvention()));
and
@using Microsoft.AspNetCore.Localization
@using Microsoft.AspNetCore.Routing
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width"/>
<title>RouteLocalization.MVC.Sample</title>
</head>
<body>
<div>
@RenderBody()
</div>
<div>
<div>Current Culture: @(Context.Features.Get<IRequestCultureFeature>().RequestCulture.UICulture.Name)</div>
<div>Current localized Route: @Url.RouteUrl(ViewContext.RouteData.Values)</div>
@{
RouteValueDictionary routeValueDictionary = new RouteValueDictionary(ViewContext.RouteData.Values);
routeValueDictionary["culture"] = null;
<div>Original version of this route: <a href="@Url.RouteUrl(routeValueDictionary)">@(Url.RouteUrl(routeValueDictionary) ?? "[null]")</a>
</div>
}
@{
RouteValueDictionary routeValueDictionaryEN = new RouteValueDictionary(ViewContext.RouteData.Values);
routeValueDictionaryEN["culture"] = "en";
<div>English (en) version of this route: <a href="@Url.RouteUrl(routeValueDictionaryEN)">@(Url.RouteUrl(routeValueDictionaryEN) ?? "[null]")</a>
</div>
}
@{
RouteValueDictionary routeValueDictionaryPT = new RouteValueDictionary(ViewContext.RouteData.Values);
routeValueDictionaryPT["culture"] = "pt";
<div>German (de) version of this route: <a href="@Url.RouteUrl(routeValueDictionaryPT)">@(Url.RouteUrl(routeValueDictionaryPT) ?? "[null]")</a>
</div>
}
<p>
<strong>All discovered Routes:</strong>
</p>
<p>
@foreach (string route in CollectRoutesApplicationConvention.Routes)
{
<div>@route</div>
}
</p>
</div>
</body>
</html>
Calling translated Urls works fine. Which Url causes this error? How does the rest of your configuration look like?
from routelocalization.
@Dresel I tried to change culture in all pages and got the same error in all of them. Here is my full configuration:
public class Startup {
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration) {
Configuration = configuration;
}
public void Configure(IApplicationBuilder applicationBuilder, IHostingEnvironment hostingEnvironment) {
StaticFileOptions staticFileOptions = new StaticFileOptions();
RewriteOptions rewriteOptions = new RewriteOptions();
if (hostingEnvironment.IsDevelopment()) {
applicationBuilder.UseDeveloperExceptionPage();
staticFileOptions.ContentTypeProvider = new FileExtensionContentTypeProvider()
.With(x => {
x.Mappings.With(y => {
y.Add(".less", "text/css");
});
return x;
});
} else {
applicationBuilder.UseStatusCodePagesWithReExecute("/errors/{0}");
}
applicationBuilder.UseRequestLocalization();
applicationBuilder
.UseRewriter(rewriteOptions)
.UseStaticFiles(staticFileOptions);
applicationBuilder
.UseMvc(routes => { routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}"); });
} // Configure
public void ConfigureServices(IServiceCollection services) {
services
.AddMvc(x => { x.Filters.Add(new MiddlewareFilterAttribute(typeof(LocalizationPipeline))); })
.AddTypedRouting()
.AddRouteLocalization(x => {
x.UseCulture("pt").WhereController(nameof(HomeController)).WhereAction(nameof(HomeController.Index)).TranslateAction("");
x.UseCulture("pt").WhereController(nameof(AboutController)).WhereAction(nameof(AboutController.Index)).TranslateAction("quem-somos");
x.UseCulture("pt").WhereController(nameof(ContactController)).WhereAction(nameof(ContactController.Index)).TranslateAction("contactos");
x.UseCulture("pt").WhereController(nameof(NewsController)).WhereAction(nameof(NewsController.Index)).TranslateAction("noticias");
x.UseCulture("pt").WhereController(nameof(WhyPortugalController)).WhereAction(nameof(WhyPortugalController.Index)).TranslateAction("porque-portugal");
x.UseCulture("pt").WhereController(nameof(ServiceController))
.WhereAction(nameof(ServiceController.FamilyLifeAndLeisure)).TranslateAction("servicos/lazer-e-familia")
.WhereAction(nameof(ServiceController.FinancialWealthPlanningAndManagement)).TranslateAction("servicos/planeamento-financeiro")
.WhereAction(nameof(ServiceController.RealEstateConsultingAndAdvisory)).TranslateAction("servicos/assessoria-imobiliaria")
.WhereAction(nameof(ServiceController.ResidenceAndCitizenshipPlanning)).TranslateAction("servicos/residencia-e-nacionalidade")
.WhereAction(nameof(ServiceController.TaxConsulting)).TranslateAction("servicos/assessoria-fiscal");
})
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization();
services.AddPortableObjectLocalization(x => x.ResourcesPath = "wwwroot/assets");
services.AddRouting(x => { x.AppendTrailingSlash = false; x.LowercaseUrls = true; });
services.AddAntiforgery(x => { x.Cookie.Name = "_antiforg"; x.FormFieldName = "_antiforg"; });
services.AddOptions();
services.Configure<Settings>(Configuration);
services.AddSingleton(x => {
RequestLocalizationOptions requestLocalizationOptions = new RequestLocalizationOptions() {
DefaultRequestCulture = new RequestCulture("en"),
SupportedCultures = new[] { new CultureInfo("en"), new CultureInfo("pt") },
SupportedUICultures = new[] { new CultureInfo("en"), new CultureInfo("pt") },
};
requestLocalizationOptions.RequestCultureProviders.Insert(0, new RouteDataRequestCultureProvider());
return requestLocalizationOptions;
});
services.AddSingleton<IConfiguration>(Configuration);
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddTransient<IUrlHelperFactory, UrlHelperFactory>();
services.AddTransient<IUrlHelper, UrlHelper>(x => (UrlHelper)x.GetService<IUrlHelperFactory>().GetUrlHelper(x.GetService<IActionContextAccessor>().ActionContext));
services.AddTransient<IMailService, MailService>();
services.AddScoped<IValidationService, ValidationService>();
services.AddScoped<SingleInstanceFactory>(x => y => x.GetService(y));
services.AddScoped<MultiInstanceFactory>(x => y => x.GetServices(y));
services
.Scan(x =>
x.FromAssembliesOf(typeof(IMediator), typeof(Startup))
.AddClasses(y => y.AssignableTo(typeof(IMediator))).AsImplementedInterfaces().WithScopedLifetime()
.AddClasses(y => y.AssignableTo(typeof(IRequestHandler<,>))).AsImplementedInterfaces().WithScopedLifetime()
.AddClasses(y => y.AssignableTo(typeof(IAsyncRequestHandler<,>))).AsImplementedInterfaces().WithScopedLifetime()
.AddClasses(y => y.AssignableTo(typeof(INotificationHandler<>))).AsImplementedInterfaces().WithScopedLifetime()
.AddClasses(y => y.AssignableTo(typeof(IAsyncNotificationHandler<>))).AsImplementedInterfaces().WithScopedLifetime());
services.Scan(x => x.FromAssembliesOf(typeof(Startup)).AddClasses(y => y.AssignableTo(typeof(IValidator))).AsImplementedInterfaces().WithScopedLifetime());
} // ConfigureServices
} // Startup
Does this help?
from routelocalization.
Can you access translated routes directly by entering in browser bar (like /pt/quem-somos)?
Do you use the RouteValueDictionary anywhere else? It sounds like you add the culture key twice...
Either upload a repo or tell me what to add to the sample project to reproduce your error or uncomment parts of your config until it works and you can isolate the problem.
from routelocalization.
I found the problem but not sure what I am doing wrong. I was trying to create links to change the culture but using only one line of code so I used:
<a href="@(Url.RouteUrl(new RouteValueDictionary(ViewContext.RouteData.Values).With(x => { x.Add("culture", null); return x; })))">EN</a>
<a href="@(Url.RouteUrl(new RouteValueDictionary(ViewContext.RouteData.Values).With(x => { x.Add("culture", "pt"); return x; })))">PT</a>
With
is a simple extension which code is the following:
public static void With(this T value, Action action) {
action(value);
}
public static R With<T, R>(this T value, Func<T, R> function) {
return function(value);
}
I was able to solve it by using
x["culture"] = null
And
x["culture"] = "pt"
Do you have a shorter way than what you use in your sample to generate culture change links?
from routelocalization.
Well we are generating routes by passing route values (controller, action, culture, ...). To create a change culture link for the current link we need the current route values and change the culture to the culture we want.
One option to get the current route values is ViewContext.RouteData.Values
. If you are on a translated route then there is already a culture (en for example) in this dictionary, so calling Add
throws the exception above. That's why it's better to use the indexer dictionary[key]
for adding / setting the culture value.
I don't know any "shorter" way, but if you want to keep your views clean, you could create an extension method for UrlHelper:
public static class UrlHelperExtension
{
public static string RouteUrlWithCulture(this IUrlHelper urlHelper, string culture)
{
var routeValueDictionary = new RouteValueDictionary(urlHelper.ActionContext.RouteData.Values);
routeValueDictionary["culture"] = culture;
return urlHelper.RouteUrl(routeValueDictionary);
}
}
and use it within your view:
<div><a href="@Url.RouteUrlWithCulture("pt")">Change Culture</a></div>
Does this help you?
from routelocalization.
Yes it does. Thank you for the help.
from routelocalization.
Related Issues (20)
- Problem with Link Generation for Route HOT 3
- Difficulty redirecting to correct culture/prefix from non-default culture HOT 3
- Assembly sign is missing
- Some notes from the MVC team HOT 5
- How to route sitemap.xml HOT 2
- No License File? HOT 1
- How to add translations to other controllers in core branch HOT 4
- ActionModels with AttributeRoutes was expected HOT 4
- Default culture in routes? HOT 2
- Make route ignore culture parameter HOT 2
- Force route to have culture value in URL HOT 1
- Get RouteValues from url string HOT 2
- Controller part is not translated HOT 2
- Adding localtization for actions containing parameters HOT 4
- AddCultureAsRoutePrefix only for one language HOT 2
- GetRouteData return empty WebAPI route instead valid MVC route HOT 2
- The state of ASP.NET Core branch HOT 6
- Is translations possible using only route attributes? HOT 6
- It seems ActionFilter is too late to apply current culture HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from routelocalization.