How to make my webform to be multi-language? - c#

I am going to write a web form via Visual Studio 2013 with Devexpress v14.1.
The web form is required to change the language with CheckedChanged event.
I have read some of the articles from Google,
but it seems that it required to set all of the controls one by one.
For example, if there are 30 labels in my web page, it is necessary to add 30 lines:
Label1.Text = ...;
Label2.Text = ...;
...
Label30.Text = ...;
What is the best approach to make multi-language web page ?
Please help!!!

Implementing multi-lingual is not as simple as you think.
Prerequisite: -
All controls which need multi-lingual on your page should be server control. e.g.
<Label runat="server" ID="lblName" Text="Type your name"></Label>
Create a resource file
To generate a local resource file from an ASP.NET Web page
Open the page for which you want to create a resource file.
Switch to Design View.
In the Tools menu, click Generate Local Resource. (It will create the a resource file in local resources folder)
Type values for each resource that you need in your application, and then save the file.
Read more Creating Resources From a Web Page
When you have successfully created a default resource file (e.g. mypage.resx) then copy/paste it and rename the copied file with the language specific e.g. mypage.fr.resx for french
Change the values to the language specific values
Asp.net uses the resx file based on the current thread culture but the problem is CheckedChanged event occurs after the Page_Load event so CheckedChanged event method is not the correct place to change thread culture.
So you will need to capture the CheckedChanged value manually in Page_Init event (which occurs before Page_Load) event from Request.Form values and set the culture
Or inside CheckedChanged save a value in session or cookie and reload the page and in Page_Init use the session/cookie value to set the thread culture

I hope these articles ASP.NET Web Page Resources Overview and How to: Retrieve Resource Values Programmatically can help you to solve your problem:
Creating Resource Files for ASP.NET Web Sites
Working with Resources in Web Pages
Selecting Resource Files for Different Languages
eg.
<%# Page Language="C#" %>
<script runat="server">
protected void Button1_Click(object sender, EventArgs e)
{
Button1.Text =
GetLocalResourceObject("Button1.Text").ToString();
Image1.ImageUrl =
(String)GetGlobalResourceObject(
"WebResourcesGlobal", "LogoUrl");
Image1.Visible = true;
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="Button1" runat="server"
OnClick="Button1_Click"
Text="Get Resources" />
<asp:Image ID="Image1" runat="server"
Visible="false" />
</div>
</form>
</body>
</html>

Take into account several aspects:
1. You have to keep track of the UICulture in your session (for example, using your SessionManager class). Then, you have to initialize in on your Page.
Code in your SessionManager class:
public string SUICulture
{
get
{
if (HttpContext.Current.Session["SUICulture"] == null)
{
HttpContext.Current.Session["SUICulture"] = "es";
}
return HttpContext.Current.Session["SUICulture"].ToString();
}
set
{
HttpContext.Current.Session["SUICulture"] = value;
}
}
Code in your Page:
protected override void InitializeCulture()
{
String currentUICulture = clsSessionManager.GetInstance().SUICulture;
if(currentUICulture != null){
UICulture = currentUICulture;
Thread.CurrentThread.CurrentUICulture = new CultureInfo(currentUICulture);
}
base.InitializeCulture();
}
2. Change the UICulture on the specific event of your page (onCheckedChanged in this case). In this example the page just offers two possible languages, English or Spanish
protected void chckOnCheckedChange(object sender, EventArgs e)
{
if (clsSessionManager.GetInstance().SUICulture== "es")
{
clsSessionManager.GetInstance().SUICulture= "en";
}else
{
clsSessionManager.GetInstance().SUICulture= "es";
}
Response.Redirect(Page.Request.Url.ToString(), true);
}
3. Change the labels of your page. Best approach: use resource files i.e. you can have two resource files.
You have to use server controls in order to achieve this. For example:
<asp:Literal ID="lblTitle" runat="server" />
Then you have to change it in your codebehind:
lblTitle.Text = GetGlobalResourceObject("Default","labelTitle").ToString();
You will find more information here
https://msdn.microsoft.com/en-us/library/fw69ke6f.aspx
4. Beside using resource files for the content of your page there is a possibility that you need to translate the menu as well (when using a sitemap).
This page show you how to do that https://msdn.microsoft.com/en-us/library/ms178426.aspx

Related

Can not disable ViewState

I have made a simple Web Form where I try to get rid of the ViewState. When I run it and press Go the label gets the value of whatever I put in the texbox. So far all good. But the textbox maintains the value I filled in. As far as I understand it this is done by the ViewState mechanism. What do I miss?
<%# Page Language="C#" AutoEventWireup="true" Inherits="SportsPlay.Sida1" ViewStateMode="Disabled" EnableViewState="false" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server" enableviewstate="false">
<div>
<asp:TextBox runat="server" ID="txtTest" ></asp:TextBox>
<asp:Button runat="server" ID="btnGo" Text="Go" OnCommand="btnGo_Command" />
<asp:Label runat="server" ID="lblResult"></asp:Label>
</div>
</form>
</body>
</html>
<script runat="server" language="C#">
void btnGo_Command(object sender, CommandEventArgs e)
{
lblResult.Text =txtTest.Text ;
}
</script>
Aside from the previous answer you can explicitly clear it on click TextBox1.Text = ""; Or Redirect to the same page should clear everything out.
The ViewState manages the information of the current page. It is utilized by the HTML pages by ASP.NET applications to maintain the state of the web form controls. By this you can save a lot of coding by maintaining the ViewState of the objects in your Web Form.
You do not need ViewState in the following situations:
The control is repopulated on every postback. If you ignore old data, and if you repopulate the server control each time the page is refreshed then you do not need ViewState.
When you complete a web page, review the controls in the page and consider what information is being passed in the view state and whether you really need all that information to be maintained. To optimize web page size, consider disabling view state in these cases.
The control is an input control and it changes only from user actions.
The control never changes.
By default, ViewState is enabled for all server controls. ViewState can be enabled and disabled in any of the following ways:
Control Level
Page Level
Application Level
Machine Level
To disable ViewState
To disable ViewState for a single control on a page, set the EnableViewState property of the control to false, as in the following:
<asp:DropDownList ID="DropDownList1" runat="server" EnableViewState="false" />
To disable ViewState for a page
To disable ViewState for a single page, set the EnableViewState attribute in the # Page directive to false, as in the following:
<%# Page Language="C#" EnableViewState="false" AutoEventWireup="true" CodeFile="URLRouting.aspx.cs" Inherits="URL_Rewriting" %>
To disable a page's View State, add the code below in the Page class of the page.
public void DisableViewState()
{
this.Init += new EventHandler(Page_Init);
}
private void Page_Init(object sender, System.EventArgs e)
{
this.EnableViewState = false;
}
To disable ViewState for a specific application
To disable ViewState for a specific application, use the following element in the Web.config file of the application:
<configuration>
<system.web>
<pages enableViewState="false" />
</system.web>
</configuration>
To disable ViewState for all applications on a Web server
To disable ViewState for all applications on a Web server, configure the element in the Machine.config file as follows:
<Machine.config >
<system.web>
<pages enableViewState="true" />
</system.web>
</Machine.config>

Issue with asp.net expression builder

I have the same issue mentioned in this question, but the accepted answer doesn't work for me. Basically I simply would like to add translations to elements (e.g. button, label) in a webforms page.
I checked other sites too, they all point to the same solution. E.g. this this MSDN article says:
For example, when localizing content automatically, you can set the Text property of a server control using expression syntax, as in this example:
<asp:Label id="label1" runat="server" text="<%$ Resources: Messages, ThankYouLabel %>" />
In the App_GlobalResources folder, you could have resource files named Messages.resx, Messages.es.resx, Message.de.resx, and so on—a Messages resource file for each language you want to support
In my case, the translation is not picked up, I see always the neutral language (English).
I made a dummy skeleton project too with only a few lines of code, there I have 2 resource files in the App_GlobalResources folder:
MyResources.resx
MyResources.nl.resx
Default.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("nl");
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("nl");
}
Default.aspx
<%-- this displays the translation (nl) --%>
<%= Resources.MyResource.MyKey %>
<%-- this displays the neutral language (en) --%>
<asp:Label ID="Label1" runat="server" Text="<%$ Resources: MyResource, MyKey %>" />
Any ideas what do I miss?
After several tries (and failures) I got it working. This answer and this MSDN page put me on the right track.
In short, I needed override the InitializeCulture method like this:
protected override void InitializeCulture()
{
UICulture = "nl";
Culture = "nl"
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("nl");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("nl");
base.InitializeCulture();
}
To make it a general solution, I had to create a new PageBase class, which is inherited by all pages, as it is nicely described here.

Creating form tag programmatically not working

I have a simple web page that contains a Literal, now I want to create a form tag in code behind.
This is an example:
if (IsPostBack)
{
Literal1.Text = "form submit";
}
else
{
Literal1.Text = "<form id='myFrom' runat='server' action='default.aspx'
method='POST'><input type='submit' value='click here'/></form>";
}
This code create the form, but when I click the submit button, it doesn't go through IsPostBack path. Why?
Note that I need it to be created and sent as an string, because I want to use it in ajax for example.
IsPostBack is only enabled when the POST request originates from ASP.NET's __doPostBack() function. See How to use __doPostBack() for how to create an async postback request with JavaScript.
An ASP.NET web form is already an HTML form and encompasses all of your controls. You are nesting a form within a form which is not legal HTML.
I'd suggest you replace your nested form with a simple button. In the click handler for the button, redirect to default.aspx.
As indicated by John Wu, you don't want to implement your code this way. Nested forms -- while browsers forgive them -- are just not the way to go, especially with ASP.Net WebForms. Sure, I was able to get your code to work, BUT if you need to ajaxify your page so that it works with the WebForms postback model, then it would be much better to use the UpdatePanel control (in conjunction with the ScriptManager control).
ASP.Net WebForms is predicated on only having a single Form element used on a page, as it relates to its postback model, so you'll want to work within that constraint.
Here's some code to demonstrate the use of the UpdatePanel to ajaxify a WebForm (and take advantage of PostBack):
...the .ASPX page:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="NestedForm_Question.aspx.cs" Inherits="StackOverflowAspNetQuestionAnswers.NestedForm_Question" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager" runat="server" />
<asp:UpdatePanel runat="server">
<ContentTemplate>
<asp:Literal ID="Literal1" runat="server" />
<asp:Button ID="SubmitButton" Text="Submit" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
...the associated code-behind class:
public partial class NestedForm_Question : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
SubmitButton.Click += SubmitButton_Click;
}
void SubmitButton_Click(object sender, EventArgs e)
{
Literal1.Text = "form submit";
}
}
You can see that in the code-behind class, the code that would need to be written to set the value of the literal control after the Button is clicked is the same whether the page is ajaxified or not.
I've changed my code to this:
if (Context.Request.Form.HasKeys()) // instead of if(IsPostBack)
{
Literal1.Text = "isPostBack";
}
else
{
Literal1.Text = "<form id='myFrom' runat='server' action='default.aspx' method='POST'><input type='submit' name='submitbtn' value='click here'/></form>";
}
Using different examples, I didn't find any exception to this. and it works well.
Any idea about this solution?
Note that in this way at least one of our elements in the form should have the name property.

Localization of ASP.NET website is not working

I am trying to localize an asp.net website, however its not working properly.
At the moment I have a user control, which I wish to localize. So inside the UserControls folder, I have created an App_LocalResources folder, and 4 files which will be used for the localization :
UCMain.aspx.resx
UCMain.aspx.it-IT.resx
UCMain.aspx.de-DE.resx
UCMain.aspx.fr-FR.resx
In the UserControls folder, I have the main UCMain.aspx and inside the UCMain.aspx, I have the following simple file:
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="UCMain.ascx.cs" Inherits="SCPerformance.UserControls.UCMain" %>
<%# Import Namespace="SCPerformance.Shared.Models" %>
<div class="PanelContainer">
<div class="ContentTitle2">
<asp:Label runat="server" ID="lblAboutText" meta:resourcekey="lblAboutTextResource1" />
</div>
</div>
Inside the localized files (resx) I have the following for all the languages:
Name Value
lblAboutTextResource1.Text Informazione
The culture is set correctly when I click on the flags I have, so that is not the problem. The problem is to retrieve the actual text, I am always getting the English version.
What could be my problem?
Thanks for your help and time.
Here's another solution that works for my asp website with 4 languages ​​in my "GlobalRessource" folder.
Have you tried this option?
C# -- overload function InitializeCulture
protected override void InitializeCulture()
{
try
{
string langID = "fr-FR";
Thread.CurrentThread.CurrentUICulture = new CultureInfo(langID);
base.InitializeCulture();
}
catch (Exception e)
{
Console.Out.WriteLine(e.Message);
}
}
ASP --> <%$ Resources:[resource directory name],[resource label name] %>
<asp:Label runat="server" ID="lblAboutText" Text="<%$ Resources:UCMain,lblAboutTextResource1 %>" ></asp:Label>

ASP.NET issue when removing Control on Page Load

I have following Index.aspx web form:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="ProblematicWebApplication.Index" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<asp:Label ID="dummyLabel" runat="server" Text="This is dummy label." />
<form id="form1" runat="server">
<div>
<asp:DropDownList ID="intDropDownList" runat="server"/>
<br />
<asp:Button Text="Submit" OnClick="OnSubmitClicked" runat="server"/>
<br />
Selected value: <asp:Label ID="selectedValueLabel" runat="server" />
</div>
</form>
</body>
</html>
And following code behind Index.aspx.cs file:
using System;
using System.Linq;
namespace ProblematicWebApplication
{
public partial class Index : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
this.intDropDownList.DataSource = Enumerable.Range(0, 11).ToArray();
this.intDropDownList.DataBind();
}
if (this.Request["remove-dummy"] != null)
this.Controls.Remove(this.dummyLabel);
}
protected void OnSubmitClicked(object sender, EventArgs e)
{
this.selectedValueLabel.Text = this.intDropDownList.SelectedValue;
}
}
}
When I run my application with no remove-dummy parameter in query string and select some value from intDropDownList and click Submit button, selected value is accordingly presented in selectedValueLabel.
But if I run my application with remove-dummy=1 parameter in query string, dummyLabel gets removed. Now when I select some value from intDropDownList and click Submit button, selected value is not correctly written to selectedValueLabel and all items from intDropDownList are removed.
Can someone explain it to me why this is happening?
Why removing unrelated dummyLabel control has influence on intDropDownList control?
Hmm, seems odd. I got it to work by moving your code that removes the control into the Page's PreInit event:
protected void Page_PreInit(object sender, EventArgs e)
{
if (this.Request["remove-dummy"] != null)
{
this.Controls.Remove(this.dummyLabel);
}
}
It seems that ViewState loading fails in postback after dummyLabel is removed in previous page load.
Details:
first study following articles:
TRULY Understanding ViewState - Infinities Loop
ASP.NET Page Life Cycle Overview
Following image shows important ASP.NET page events and where in between ViewState handling takes place.
So what happens when declarative Control dummyLabel is removed? Here is a process:
Page is requested for the first time with query string parameter remove-dummy=1.
In Page_Load event declarative Control dummyLabel is removed.
Before SaveStateComplete event, ViewState is saved. There is no control dummyLabel in control tree, so its ViewState won't be saved.
Submit button is clicked.
Between InitComplete and PreLoad events, ViewState gets loaded. This is where it breaks because control tree now contains dummyLabel (dummyLabel gets removed after, in Load event) and ASP.NET fails in recursively loading ViewState into Page control tree. My assumption is that ViewState and Page control tree are tightly coupled and recursive ViewState loading fails as a consequence of this tight coupling.
One more situation that backs-up this theory: if you place dummyLabel at the very end of the page, issue doesn't happen anymore, because all other controls in Page control tree that come before dummyLabel already picked correct values from ViewState (ViewState structure and Page control tree are tightly coupled). If there were more controls after dummyLabel, their ViewState loading would fail.
To resolve this issue, all declarative Controls (defined in ASPX file) that should be removed, must be removed before ViewState loading takes place - in InitComplete event or any other event before it.

Categories