I have a web application that uses localization to show either English or French for our French Canadian Customers.
It is working just fine based on the users regional settings.
We have a need however to allow the user to switch back to English if their regional settings are set to French.
Is it possible to override the users regional setting if he so desires? if so...how would I code this? (for example having a link on the layout page that says English, clicking this would then change it back to English or back to French)
Also, I am using resource files to save the text strings and using the same set of views.
Somewhere in your code after they click a button to select a language:
Session["customLocalization"] = "de-DE"; //Or whatever language
In your Global.asax
protected void Application_BeginRequest(object sender, EventArgs e)
{
String sessionOverrideLocale;
if (HttpContext.Current != null && HttpContext.Current.Session != null)
{
sessionOverrideLocal = (String) HttpContext.Current.Session["customLocalization"];
}
if (sessionOverrideLocale != null)
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo(sessionOverrideLocale);
Thread.CurrentThread.CurrentCulture = new CultureInfo(sessionOverrideLocale);
}
}
Yes, it is possible but I do not currently have access to the code I most recently worked on where we allowed the user to change their current rendered region.
Here is a blog post that goes into great detail regarding doing this. He has an older post that I believe uses MVC3 and then this newer one is written from the perspective of MVC4, so this should have you covered.
I hope it helps:
http://geekswithblogs.net/shaunxu/archive/2012/09/04/localization-in-asp.net-mvc-ndash-upgraded.aspx
Related
i'm working in Multilingual grails application (English and arbaic) , i want when the user chooses Arabic language the view's labels will be on the right side of the page and in English on the left side , how this can be achieved ?
thanks
You can use internationalization in grails through messages.properties file, you can define message signature in files and and they can be accessed through ?lang=es on the URL, you may need to have two files one for english and another for Arabic.
for example define in the messages.properties:
vendor.link.dashboardLink = Vendor Dashboard
and on the GSP page you can access it like:
<g:message code="vendor.link.dashboardLink" />
you can find more about internalization at grails doc have a look at http://grails.org/doc/2.2.1/guide/i18n.html
If the views have differences beyond simple string substitution, I would recommend using a different set of views based on locale:
Example controller code:
import org.springframework.web.servlet.support.RequestContextUtils as RCU
class ExampleController {
final static String englishLanguageCode = new Locale('en').getLanguage()
final static String arabicLanguageCode = new Locale('ar').getLanguage()
def differentViews() {
def currentLocale = RCU.getLocale(request)
switch(currentLocale.language) {
case englishLanguageCode:
render view: 'englishView'
break
case arabicLanguageCode:
render view: 'arabicView'
break
default:
// pick a default view or error page, etc.
}
}
}
Mobile display modes in ASP.NET MVC 4 stop serving the correct views after about an hour of uptime, despite browser overrides correctly detecting an overridden mobile device.
Recycling the application pool temporarily solves the problem.
The new browser override feature correctly allows mobile devices to view the desktop version of a site, and vice-versa. But after about an hour of uptime, the mobile views are no longer rendered for a mobile device; only the default desktop Razor templates are rendered. The only fix is to recycle the application pool.
Strangely, the browser override cookie continues to function. A master _Layout.cshtml template correctly shows "mobile" or "desktop" text depending on the value of ViewContext.HttpContext.GetOverriddenBrowser().IsMobileDevice, but the wrong views are still being rendered. This leads me to believe the problem lies with the DisplayModes.
The action in question is not being cached:
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
I am using 51Degrees for mobile detection, but I don't think this should affect the overridden mobile detection. Is this a bug in DisplayModes feature for ASP.NET MVC 4 Beta & Developer Preview, or am I doing something else wrong?
Here is my DisplayModes setup in Application_Start:
DisplayModeProvider.Instance.Modes.Insert(0, new DefaultDisplayMode("iPhone")
{
ContextCondition = context =>
context.GetOverriddenBrowser().IsMobileDevice
&& (context.Request.UserAgent.IndexOf("iPhone", StringComparison.OrdinalIgnoreCase) >= 0
|| context.Request.UserAgent.IndexOf("Android", StringComparison.OrdinalIgnoreCase) >= 0
|| !context.Request.Browser.IsMobileDevice)
});
/* Looks complicated, but renders Home.iPhone.cshtml if the overriding browser is
mobile or if the "real" browser is on an iPhone or Android. This falls through
to the next instance Home.Mobile.cshtml for more basic phones like BlackBerry.
*/
DisplayModeProvider.Instance.Modes.Insert(1, new DefaultDisplayMode("Mobile")
{
ContextCondition = context =>
context.GetOverriddenBrowser().IsMobileDevice
});
This is a known issue in MVC 4 (Codeplex: #280: Multiple DisplayModes - Caching error, will show wrong View). This will be fixed in the next version of MVC.
In the meantime you can install a workaround package available here: http://nuget.org/packages/Microsoft.AspNet.Mvc.FixedDisplayModes.
For most applications simply installing this package should resolve the issue.
For some applications that customize the collection of registered view engines, you should make sure that you reference Microsoft.Web.Mvc.FixedRazorViewEngine or Microsoft.Web.Mvc.FixedWebFormViewEngine, instead of the default view engine implementations.
I had a similar issue and it turned out to be a bug when mixing webforms based desktop views with razor based mobile views.
See http://aspnetwebstack.codeplex.com/workitem/276 for more info
Possibly a bug in ASP.NET MVC 4 related to caching of views, see:
http://forums.asp.net/p/1824033/5066368.aspx/1?Re+MVC+4+RC+Mobile+View+Cache+bug+
I can't speak for this particular stack (I'm still in MVC2) but check your output caching setup (either in your controllers or views - and in your web.config in your app and at the machine level). I've seen it work initially for the first few users and then a desktop browser comes in right around the time ASP decides to cache, then everyone gets the same view. We've avoided output caching as a result, hoping this would get addressed later.
If you want all mobile devices to use the same mobile layout you can use
DisplayModeProvider.Instance.Modes.Insert(1, new DefaultDisplayMode("Mobile")
{
ContextCondition = context =>
context.GetOverriddenBrowser().IsMobileDevice
});
And of course you need to make a view in the shared layout folder named _Layout.Mobile.cshtml
If you want to have a separate layout for each type of device or browser you need to do this;
DisplayModeProvider.Instance.Modes.Insert(0, new DefaultDisplayMode("Android")
{
ContextCondition = (context => context.GetOverriddenUserAgent().IndexOf
("Android", StringComparison.OrdinalIgnoreCase) >= 0)
});
DisplayModeProvider.Instance.Modes.Insert(0, new DefaultDisplayMode("iPhone")
{
ContextCondition = (context => context.GetOverriddenUserAgent().IndexOf
("iPhone", StringComparison.OrdinalIgnoreCase) >= 0)
});
DisplayModeProvider.Instance.Modes.Insert(0, new DefaultDisplayMode("Mobile")
{
ContextCondition = (context => context.GetOverriddenUserAgent().IndexOf
("IEMobile", StringComparison.OrdinalIgnoreCase) >= 0)
});
And of course you need to make a view in the shared layout folder for each named
_Layout.Android.cshtml
_Layout.iPhone.cshtml
_Layout.Mobile.cshtml
Can you not just do this?
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
// Code removed for clarity.
// Cache never expires. You must restart application pool
// when you add/delete a view. A non-expiring cache can lead to
// heavy server memory load.
ViewEngines.Engines.OfType<RazorViewEngine>().First().ViewLocationCache =
new DefaultViewLocationCache(Cache.NoSlidingExpiration);
// Add or Replace RazorViewEngine with WebFormViewEngine
// if you are using the Web Forms View Engine.
}
So guys here is the answer to all of your worries..... :)
To avoid the problem, you can instruct ASP.NET to vary the cache entry according to whether the visitor is using a mobile device. Add a VaryByCustom parameter to your page’s OutputCache declaration as follows:
<%# OutputCache VaryByParam="*" Duration="60" VaryByCustom="isMobileDevice" %>
Next, define isMobileDevice as a custom cache parameter by adding the following method override to your Global.asax.cs file:
public override string GetVaryByCustomString(HttpContext context, string custom)
{
if (string.Equals(custom, "isMobileDevice", StringComparison.OrdinalIgnoreCase))
return context.Request.Browser.IsMobileDevice.ToString();
return base.GetVaryByCustomString(context, custom);
}
This will ensure that mobile visitors to the page don’t receive output previously put into the cache by a desktop visitor.
please see this white paper published by microsoft. :)
http://www.asp.net/whitepapers/add-mobile-pages-to-your-aspnet-web-forms-mvc-application
Thanks and Keep coding.....
I need to switch Locate in my app between Arabic and English.
I have the following code to switch locale:
if (Locale.getDefault() == Locale.get(Locale.LOCALE_ar, null)) {
Locale.setDefault(Locale.get(Locale.LOCALE_en, null));
} else {
Locale.setDefault(Locale.get(Locale.LOCALE_ar, null));
}
And in my app I have the following resource files:
appName.rrh
appName.rrc
appName_ar.rrc
appName_en.rrc
And I have a button which uses a localized string as follows:
subscribeButton = new ButtonField(res.getString(LANG), ButtonField.CONSUME_CLICK);
My problem is when the locale is changed to Arabic, the UI flips (Arabic is right to left), and switching it again to English flips it again, but all without the text in the button changing. Please guide me on what I'm doing wrong.
Its because, you have created the button field with the text which was relevant for that locale. Once the locale changes, you will have to re set the buttonField text as
subscribeButton.setLabel(res.getString(LANG));
I have a BrowserField in my app, which works great. It intercept NavigationRequests to links on my website which go to external sites, and brings up a new windows to display those in the regular Browser, which also works great.
The problem I have is that if a user clicks a link to say "www.google.com", my app opens that up in a new browser, but also logs it into the BrowserHistory. So if they click back, away from google, they arrive back at my app, but then if they hit back again, the BrowserHistory would land them on the same page they were on (Because going back from Google doesn't move back in the history) I've tried to find a way to edit the BrowserField's BrowserHistory, but this doesn't seem possible. Short of creating my own class for logging the browsing history, is there anything I can do?
If I didn't do a good job explaining the problem, don't hesitate for clarification.
Thanks
One possible solution to this problem would be to keep track of the last inner URL visited before the current NavigationRequest URL. You could then check to see whether the link clicked is an outside link, as you already do, and if it is call this method:
updateHistory(String url, boolean isRedirect)
with the last URL before the outside link. Using your example this should overwrite "www.google.com" with the last inner URL before the outside link was clicked.
Here is some half pseudocode/half Java to illustrate my solution:
BrowserFieldHistory history = browserField.getHistory():
String lastInnerURL = "";
if navigationRequest is an outside link {
history.updateHistory(lastInnerURL, true);
// Handle loading of outer website
} else {
lastInnerURL = navigationRequest;
// Visit inner navigation request as normal
}
http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/browser/field2/BrowserFieldHistory.html#updateHistory(java.lang.String, boolean)
I had a similar but a little bit different issue. Special links in html content like device:smth are used to open barcode scanner, logout etc and I wanted them not to be saved in BrowserFieldHistory. I found in WebWork source code interesting workaround for that. All that you need is throw exception at the end like below:
public void handleNavigationRequest( BrowserFieldRequest request ) throws Exception {
if scheme equals to device {
// perform logout, open barcode scanner, etc
throw new Exception(); // this exception prevent saving history
} else {
// standard behavior
}
}
So, after much research on whether or not we should the CEWP or the HTML Field Control on an external facing SharePoint site, we settled on using the Field Control (much thanks to AC). Now, we are having an issue that all the blogs I read say should not be an issue.
When we put a relative URL into the HTML Editor and hit OK, it is automatically changed to an absolute URL. This is apparently a "feature" of Internet Explorer from some of the research I have been doing. TinyMCE has a work around for this. I was wondering if there was some work around for the SharePoint control that I am missing.
This is kind of a big issue for us because we have an authoring site and the www site. So, when the authoring is done on the authoring site and all the links get migrated to the www site, they are http:// authoring.domain.com/en-us/Pages/... instead of /en-us/Pages/...
I encountered this issue as well. We had custom site fields and content types deployed via feature. The RichText property of the HTML Field is properly as true in caml, but once deployed the SPField in the root web fields collection and every Pages list the RichText attribute becomes false.
I was able to successfully resolve the issue by using a feature receiver on the feature that deploys the site columns and content types. My code loops every web in the site and then iterates over the fields to update them.
code snippet:
private void processweb(SPWeb web)
{
SPList list = web.Lists["Pages"];
SPField field;
for (int i = 0; i < list.Fields.Count; i++)
{
field = list.Fields[i];
//to work around a sharepoint defect ... make html fields work in richtext mode
if (field != null && string.Compare(field.TypeAsString, "HTML", true) == 0 && (field as SPFieldMultiLineText).RichText == false)
{
(field as SPFieldMultiLineText).RichText = true;
field.Update(true);
}
}
foreach (SPWeb w in web.Webs)
{
processweb(w);
}
}