A significant improvement in the web application localization have been done in VS2005. Now, the values are assigned automatically in a much better way.
To make your web page localizable:
1- Go to (Tools)
2- Click (Generate Local Resource)
3- wait until getting the following message:Finished creating resource content and adding ‘meta:’ attributes, the progress is now done.
you will find that a new folder named “App_LocalResources” have been created. In this folder you will find that a resource file have been created having the name <your page name>.asp.resx . In this file you will find that all of your controls properties have been added as entries in the resouce file but “Resource1″ appended to the controls names.
Now, to add another language to your application you have to copy the resx file and add your culture name before the resx extention. (e.g. Default.asp.ar-eg.resx)
Localization have been improved in this version of Visual Studio but in needs more and more enhancement.
May 18, 2008
A lot of people always asking about how to localize ASP applications in .NET 1.1
Don’t expect too much from Visual Studio 2003 it provide nothing in this case.
if you want to build a localized web application you have to do it with your code.
and all of the localized controls MUST be server controls as you usually use a resource manager to retrieve the values from resource files and assign it to controls in runtime.
Take care that you need to retrieve the user culture (browser language) from the request object. Because the currentCulture is the server system culture.
You can made a loop to assign the resource entries to the controls properties but it will stay a very stupid process. Always there are keys forgetting and miss-spilling.
The conclusion: It was horrible believe me!!!
May 18, 2008
To add a text from a resource file into your SharePoint ASPX page you have to place this code where ever you want this text to places.
<%$Resources:MyResource, MyName%>
where:
- MyResource: is the resource file name.
-MyName: is the resource entry key.
Your resource files must be placed in this directory:
..\12\CONFIG\Resources\
all resource files in this directory are copied to the global resources for every web application when it’s creating.
if the webapplication already exists place the resources files in this directory:
C:\Inetpub\wwwroot\wss\VirtualDirectories\<port>\App_GlobalResources\
where <port> is the the web application port
May 16, 2008
In this post, I will discuss the logic contained in the data layer. The data layer logic is all in stored procedures and functions.
First, Let us discuss the logic for the Languages table. The following stored procedures may be defined on the languages table:
- AddLanguage: Add new language to the system. You must take care that this stored procedure not only adds a record in the languages table but it also adds a record for that language into all child tables.
- DeleteLanguage: Delete language from the system. You need to remove all the records related to that language from child tables. You have to check also if it’s the default language for any user then he/she has to change it.
- UpdateLanguage: Update the details for a language.
- GetLanguageDetailsById: Retrieves all the language data using language ID.
- GetAllLanguages: Retrieves all the languages supported by the system.
Then we can define a group of stored procedures on every multilingual parent-child tables:
-
AddRecord: This stored procedure is defined on the parent child records. It first adds a record in the parent table then adds its child record for a specific language and adds empty child record for each other languages. This stored procedure may use two other stored procedures or functions:
- AddParentRecord.
- AddChildRecord.
-
UpdateRecord: Updates a parent record and one of its related child so it needs to take a language parameter. Also, it needs another two stored procedures:
- UpdateParentRecord.
- UpdateChildRecord.
-
DeleteRecord: Deletes a record from parent table and all of its related child records. Again, it needs the two stored procedures:
- DeleteParentRecord.
- DeleteChildRecord.
- GetRecoredByLang: Retrieves the parent record and one of its children defined using the language paramenter.
- GetAllRecoreds: Retrieves the parent record and all of its children.
After developing these procedures for all tables, you need to move to the data access layer. In this layer, you have to make functions that allows you to connect to the database and access your tables and stored procedures. It’s so basic and straight forward so I will skip it.
Next time, I will talk about the business logic.
May 16, 2008
After taking a look on the system, in this post I will describe the suggested design for the Data Layer.
In the data layer we need to have a place to store the languages included in the system. This design support dynamic number of languages even while the system is running. So, a table to store the languages is needed.

In this table we have the Language ID (LangID) that stored a number uniquely indentifies the language I think using the Local ID as LangID will be better or it can be added as a new column in the table. Then we have the language name stored the name of the language written in that language so this column must have NVarChar type. Also we have Language direction identify if the language displayed in right-to-Left or left-to-write order. This information can be retrieved from the CultureInfo object so we can neglect it from the table.
Sometimes the system users table has a column that refers to the default language for the user. Some times its gained from the current culture of the operating system deployed in the user machine. I think prefer storing it in the users table.

Let us move now for the most important part of the system. How to design the database to support multilingual content? First design your database without considering its multilingual. Then, for each table has columns may contain information varying from language to another: first: leave the columns that not depending on the language in the same table then add a new table have a composed primary key (the key from the parent table and the language) and move all the columns depending on the language into that table. So in the new table the parent table primary key will be a foreign key to the parent table.

So, if we have a branches table contains: branch id, name, address, manager and telephone number. We can put the branch ID, manager and telephone in the parent table. While the child table will contains branch ID, language, name and address. Branch ID is a primary key for the parent table. In the child table, the primary key is composed from branch ID and language. Branch ID is a foreign key in the child table.

So if we have the branch data as following:
|
ID
|
English Name
|
Arabic Name
|
Manager ID
|
Telephone
|
English Address
|
Arabic Address
|
|
1
|
Cairo Branch
|
فرع القاهرة
|
200
|
+2022000
|
Cairo
|
القاهرة
|
Then we need to add a record the branch table:
|
ID
|
Manager ID
|
Telephone
|
|
1
|
200
|
+2022000
|
And two records in the branch details table:
|
ID
|
Lang
|
Branch Name
|
Branch Address
|
|
1
|
1025
|
فرع القاهرة
|
القاهرة
|
|
1
|
1033
|
Cairo Branch
|
Cairo
|
In the next post I will continue the talk about the data layer
May 15, 2008
In the languages worked left-to-right (like Arabic) its not working well. (see the photos) You will notice that the words will not have the right order.

Also there are some bugs in the graphics in case of right-to-left:

May 4, 2008
-
First you need to have your resource files. Place them directly under the project node. For Example add:
-
MyResource.resx
Add a new resource entry in the file:
Key: category - Value: MyNewCategory
Key: property - Value: MyNewProperty
Key: description - Value: MyNewDescription
-
MyResource.ar-sa.resx
Add a new resource entry in the file:
Key: category - Value: MyNewCategory
Key: property - Value: MyNewProperty
Key: description - Value: MyNewDescription
Take care that these resources files must be embedded resources.
Place the following attribute before the class:
[XmlRoot(Namespace = "projectname")]
- Now you have to override the LoadResource function to get the data from your resource files:
- public
override
string LoadResource(string id)
{
ResourceManager rm = new
ResourceManager(“projectname.MyResource”, this.GetType().Assembly);
return rm.GetString(id);
}
- Before the property you place the “ResourcesAttribute” attribute like the following
[ResourcesAttribute(
"property",
"category",
"description")]
[WebPartStorage(Storage.Shared)]
[Browsable(true)]
public string MyProp_Localized
{
get
{
return _ MyProp_Localized;
}
set
{
_MyProp_Localized = value;
}
}
To deploy this web part, use the regular procedure of deploying web part. But you must take care that you will need to deploy the every resources dlls in “..\bin\debug” subdirectory to the Global Assembly Cash (in” windows\assembly” directory). You will find a subdirectory for each culture you have in the project under this directory you will find a projectname.resources.dll file you have to deploy this file to the GAC.
May 4, 2008
-
First you need to have your resource files. Place them directly under the project node. For Example add:
-
MyResource.resx
Add a new resource entry in the file:
Key: hello
Value: Hello
-
MyResource.ar-sa.resx
Add a new resource entry in the file:
Key: hello
Value:أهلا
Take care that these resources files must be embedded resources.
-
In the render function add the following code:
ResourceManager rm = new
ResourceManager(“projectname.MyResources”,this.GetType().Assembly);
writer.Write(rm.GetString(“hello”));
To deploy this web part, use the regular procedure of deploying web part. But you must take care that you will need to deploy the every resources dlls in “..\bin\debug” subdirectory to the Global Assembly Cash (in” windows\assembly” directory). You will find a subdirectory for each culture you have in the project under this directory you will find a projectname.resources.dll file you have to deploy this file to the GAC.
May 4, 2008