I am trying to localize my web page, and have done the following :
Added resource files with some example strings
Added a call to a method to set culture and ui culture on the click event of flag icons :
public void SetCulture(string culture)
{
Thread.CurrentThread.CurrentCulture = new CultureInfo(culture);
Thread.CurrentThread.CurrentUICulture = new CultureInfo(culture);
}
And I have made reference to my resource file strings in my web page :
#Resources.General.String1
I have stepped through my code and the culture is successfully changed in my SetCulture method, but the string does not change on the web page. Can anybody advise why?
I don't understand what you mean with the click event in a ASP.NET MVC application. I would use routing to set the new language. A sample you can find at Localization with ASP.NET MVC using Routing.
Instead of using a Javascript event, you have to reload the whole page.
Related
I am trying to port a WebForm app to MVC 6 and am having an issue with getting resources from a resx file. The code in the controller class returns only default resx values.
I tried both setting Thread.CurrentThread.CurrentCulture & Thread.CurrentThread.CurrentUICulture as well as setting Resources.MyResouces.Culture to specific culture, but Resources.MyResouces.Key still returns only the default. What could be the problem?
public IActionResult MyAction(){
Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture =
Resources.test.Culture = CultureInfo.GetCultureInfo("fr-FR");
// The line below still returns the default English resource value
var localizedValue = Resources.test.test_key;
}
WebForms to Asp.Net Core is a pretty huge leap to take. I would recommend starting with the Asp.Net Core localization sample on GitHub to get a clearer picture of how it works.
In particular, you may need to do some more configuration in your Startup.cs file.
I am trying to develop a MVC3 (razor) application with Select language functionality.
Using the following view as a Partial view on _Layout.cshtml
_SelectCulture
<text>
#Html.ActionLink("English", "SetCulture", new { controller = "Culture", culture = "en-GB" })
|
#Html.ActionLink("Welsh", "SetCulture", new { controller = "Culture", culture = "cy-GB" })
</text>
<div>
#System.Threading.Thread.CurrentThread.CurrentUICulture.ToString()
</div>
CultureController
public ActionResult SetCulture(string culture)
{
System.Globalization.CultureInfo ci = new System.Globalization.CultureInfo(culture);
System.Threading.Thread.CurrentThread.CurrentCulture = ci;
System.Threading.Thread.CurrentThread.CurrentUICulture = ci;
return RedirectToAction("Index", "Home");
}
But its Still not changing the Language.
Any help please.
Thanks
Well, you are changing the language of the current thread. The current thread ends with the current request which is a little bit later after your controller action executes. Then you are redirecting to some other controller action. Then ASP.NET spawns a new thread to serve this request which obviously doesn't have the culture set.
So you will have to persist this change somewhere. Basically there are 3 different approaches:
route variable
cookies
session
I am putting them in the order of preference. The first approach consists into integrating a {culture} token in all your routes. IMHO this is the best approach in terms of SEO as well. So you will redirect for example to /fr/home/index if you want to get your site in French. You could then use a custom action filter attribute which will run before each action, inspect the culture route parameter and set the current thread culture (this time for the current action).
Cookies and sessions also involve persisting the current language between the requests. In the first example this is done on the client whereas in the second it is done in the server. Once again a custom action filter could be used to read the value of the language before each action and reflect the current thread culture.
You may take a look at the following guide which uses Session to persist the current language.
There were questions about multilingual apps in MVC here on SO but they were mostly answered by giving details about implementing Resource files and then referencing those Resource strings in Views or Controller. This works fine for me in conjunction with the detection of user's locale.
What I want to do now is support localized routes. For instance, we have some core pages for each website like the Contact Us page.
What I want to achieve is this:
1) routes like this
/en/Contact-us (English route)
/sl/Kontakt (Slovenian route)
2) these two routes both have to go to the same controller and action and these will not be localized (they will be in English because they are hidden away from the user since they are part of the site's core implementation):
My thought is to make the Controller "Feedback" and Action "FeedbackForm"
3) FeedbackForm would be a View or View User control (and it would use references to strings in RESX files, as I said before, I already have set this up and it works)
4) I have a SetCulture attribute attached to BaseController which is the parent of all of my controllers and this attribute actually inherits FilterAttribute and implements IActionFilter - but what does it do? Well, it detects browser culture and sets that culture in a Session and in a cookie (forever) - this functionality is working fine too. It already effects the Views and View User Controls but at this time it does not effect routes.
5) at the top of the page I will give the user a chance to choose his language (sl|en). This decision must override 4). If a user arrives at our website and is detected as Slovenian and they decide to switch to English, this decision must become permanent. From this time on SetCulture attribute must somehow loose its effect.
6) After the switch, routes should immediately update - if the user was located at /sl/Kontakt
he should immediately be redirected to /en/Contact-us.
These are the constraints of the design I would like. Simply put, I do not want English routes while displaying localized content or vice-versa.
Suggestions are welcome.
EDIT:
There's some information and guidance here - Multi-lingual websites with ASP.NET MVC, but I would still like to hear more thoughts or practices on this problem.
Translating routes (ASP.NET MVC and Webforms)
How about this?
Create custom translate route class.
Localization with ASP.NET MVC using Routing
Preview:
For my site the URL schema should look
like this in general:
/{culture}/{site}
Imagine there is a page called FAQ,
which is available in different
languages. Here are some sample URLs
for these pages:
/en-US/FAQ /de-DE/FAQ /de-CH/FAQ
Why not create the action names desired and simply RedirectToAction for the single, real implementation?
public ActionResult Kontakt() {
return RedirectToAction("Contact");
}
public ActionResult Contact() {
return View();
}
I just used a simple solution with "Globalization Resources", like this:
routes.MapRoute(
"nameroute", // Route name
App_GlobalResources.Geral.Route_nameroute+"/{Obj}", // URL with parameters
new { controller = "Index", action = "Details", Obj = UrlParameter.Optional } // Parameter defaults
);
But, you could customize as needed.
I am just beginning to localize an ASP.NET MVC application. Most of the strings will be defined in resource files and retrieved via Matt's Localization Helpers. Other strings must be stored in a database.
My Question:
Should I set CurrentUICulture early in the request pipeline and use that throughout the application, or directly use Request.UserLanguages[0] whenever needed?
Right now I'm thinking that I should set CurrentUICulture in Application_BeginRequest. The implementation would look something like this:
protected void Application_BeginRequest(object sender, EventArgs e)
{
var cultureName = HttpContext.Current.Request.UserLanguages[0];
Thread.CurrentThread.CurrentUICulture = new CultureInfo(cultureName);
}
Is this the best place to set CurrentUICulture and is Request.UserLanguages[0] the best place to get that info?
Update:
Ariel's post shows this can be defined without code, using web.config
<system.web>
<!--If enableClientBasedCulture is true, ASP.NET can set the UI culture and culture for a Web page automatically, based on the values that are sent by a browser.-->
<globalization enableClientBasedCulture="true" culture="auto:en-US" uiCulture="auto:en"/>
Here is a sample using an HttpModule:
http://weblogs.manas.com.ar/smedina/2008/12/17/internationalization-in-aspnet-mvc/
Other options, create a base Controller class and implement the localization logic there.
Or use an action filter attribute, but you'll have to remember to add it on every controller or combine this approach with the base Controller class.
Request.UserLanguages[0] can only be a hint what language the users wishes to see. Most users dont know where to change the browser language.
Another point: Dont be sure that Request.UserLanguages[0] is a valid language. It can even be null. (Not sure what bots have there)
You usually have a Language chooser on the page. Once a user has selected a language there, it is stored in a cookie, session or url. I like to use url because I think it looks pretty.
If a user sees your page without having set a language on your page, you should check if Request.UserLanguages[0] is a language you support and set Thread.CurrentThread.CurrentUICulture.
I use a filter to set Thread.CurrentThread.CurrentUICulture. Thats ok as long as no other filter is using Thread.CurrentThread.CurrentUICulture. Otherwise you would need to set the right execution order for filters.
I also use Matts helper and it worked very well so far.
i created a new solution and it builds fine targeting framework 4.0 but when i run it, my browser comes up saying:
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /
any ideas on how to debug this?
Try adding the default.aspx page that comes with the asp.net mvc 1.0 project template. I had a similar issue running mvc 2 out of the box on a computer with IIS 5 (XP), and that did the trick.
Default.aspx:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="YourNamespace.Website.Default" %>
<%-- Please do not delete this file. It is used to ensure that ASP.NET MVC is activated by IIS when a user makes a "/" request to the server. --%>
Default.aspx.cs:
using System.Web;
using System.Web.Mvc;
using System.Web.UI;
namespace YourNamespace.Website
{
public partial class Default : Page
{
public void Page_Load(object sender, System.EventArgs e)
{
// Change the current path so that the Routing handler can correctly interpret
// the request, then restore the original path so that the OutputCache module
// can correctly process the response (if caching is enabled).
string originalPath = Request.Path;
HttpContext.Current.RewritePath(Request.ApplicationPath, false);
IHttpHandler httpHandler = new MvcHttpHandler();
httpHandler.ProcessRequest(HttpContext.Current);
HttpContext.Current.RewritePath(originalPath, false);
}
}
}
You don't need to add the default.aspx page described above.
The browser will display this 404 message if you add and run a new Empty ASP.NET MVC 2 application "out of the box".
This is because of the default route that is defined in global.asax.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
You can see it is looking for a controller called Home and an action called Index.
When creating a new empty project it's left to you to create the Home controller and Index action (they are not there in an empty project), then create the view for the Index action too.
My guess is that you need to reregister or enable the framework under IIS.
Try running aspnet_regiis from the appropriate framework tree and / or make sure that the proper framework version is allowed under IIS web extensions.