|
You can set the language of every resource item.
Simply right-click on the resource item.
-----
Geert
Need an advanced auto-update feature for your software? Try Updater, it's free!
Visit my website: www.gvhsoftware.org
|
|
|
|
|
Good Article.
I have a small doubt regarding Globalization/Localization. Hope you can help me out.
I have a web form application where i need to provide more than 50 different localized resource supports. Apart from this, my application supports rich use of stored data (Sql Server Database) and obviously have few list of Listing controls (Repeater , Grid etc).
My requirement comes like this,
a) I need to provide full localized language support in all data which is displaying in each and every page. Regardless of, the name of controls, content of controls etc. To be concise, which ever text that i am displaying through page, need to be localized based on user selected language.
b) Each and every setup needs to contain all supported languages. So user can switch and view content of site in different language.
I stuck in,
1) I am not sure how to localize stored data in database.
2) How will I give or from where i generate localized information for all supported language.
It would be grate if you can help me out through your valid comments.
Sreejith Nair
[ My Articles ]
|
|
|
|
|
Hi,
This article covers the translation of strings in an application. What you need, is much more. You want different screens for every language.
This simple means you have to copy the complete resource dll to make it local. Microsoft has some greate articles about it.
About the database. I should not translate items in a database. The database is the document. The application around the document can change to the user data, but I think the document should stay the same. Because what if a language is added after a few months? In that case, your database does not contain valid data anymore.
Best regards,
Geert
Want to spread the newest version of your software automatically for free? Use Updater!
Visit my website: www.gvhsoftware.org
|
|
|
|
|
|
|
Sorry, but I would not recommend your article for anyone in need to incorporate multilingual support in his/her application.
First of all, strings are not the only thing to take care of. You must take care about calendar, time, currency, float number format in strings, national preferences in colors, control size and captions, etc.
Part of multilingual support should reside in an app itself (use Unicode, local aware date/time functions, etc.)
The other part - GUI layout, colors, etc, - should be in a resource dll.
All this is described in great details on MSDN under title 'Localization'.
geoyar
|
|
|
|
|
As Geert said in his introduction he only needed his "strings" to be in more than one language.
"What I really needed were simple .h and .cpp files which are able to load a language DLL and extract the strings I need."
I think this article helps everyone who is looking for information on how to do this in a simple and correct way.
Great job Geert!
@geoyar : Not flame intended.
|
|
|
|
|
If you are using MFC applicaiton, with or without extension DLL, I believe
Multiple language support for MFC applications with extension DLL[^] is easier. Only do the code changes in "Application Code Changes" and "DLL Code Changes", then you are done. Even for future new languages.
Simple is beauty.
---
Herbert Yu
Are you sure the speed of computer industry is proper? Are you sure the software you released is a bug free one?
|
|
|
|
|
|
How to change menu, icons, toolbars etc. this way e.g. in MDI application ? Don't forget, that not all icons and pictures have the same meening in different countries. I use multiple dlls as well, but with all resources and I change them by calling LoadLibrary and AfxSetResourceHandle.
Fredy "KRUGER" Pumpicka
|
|
|
|
|
On my way ..I'm using the below code..
-----
FreeLibrary(AfxGetResourceHandle());
HINSTANCE dll = LoadLibrary("chinese.dll");
AfxSetResourceHandle(dll);
// delete last menu
SetMenu(NULL);
::DestroyMenu(m_hMenuDefault);
// create new menu
CMenu menu;
menu.LoadMenu(IDR_MAINFRAME);
SetMenu(&menu);
m_hMenuDefault = menu.GetSafeHmenu();
|
|
|
|
|
Hello Geert. Let me to make some considerations. Often who executes the translation is not a programmer. Above all when the application is much vertical one and therefore make use of terms or expressions many techniques. To the subject that it will execute the translation is necessary to transmit a list of the terms to translate. The same one will give back an other list in which, to flank of the terms in the native language they are indicates the same ones translated.
If it could Be used rows external as dictionary of the terms the suguenti advantages could be obtained:
1) the translator could verify in real Time the result of its translation
2) would not be necessary to predispose to the inside of the application of numerous string tables.
3) In every moment he could be added new rows of dictionary without having to take part in the application.
I have realized one solution of this type. Let me know if are intrested int.
EzioXia
P.s.
Sorry for my bad english
|
|
|
|
|
Hi EzioXia,
This is indeed a good approach. What is possible is add the values to a XML file. However, sometimes you don't want the users to be able to edit the text.
I received a mail last week about another approach: using an access database.
I am interested in your approach too. If it is ok, I can add it to this article (of course with references to you). Then the user can choose between 3 different types of translating applications:
1) Dll's
2) XML (dictionary files)
3) Access database
I want the class to support all of these solutions, which will make it very useful. However, it must be done without using MFC, so I have to check how I can communicate with an access database without using MFC.
Best regards,
Geert
Want to spread the newest version of your software automatically? Use Updater!
Visit my website: http://geert.yoki.org
|
|
|
|
|
One problem with translating resources (mostly strings) from one language to another is the length of the displayed string. You most times have to resize the dialogs, forms, static texts, etc. to fit the translated text.
One small example of what I am saying, is say you have a dialog/form with a button that has the following text "Save As...", and you want to translate it to the greek text "Αποθήκευση ως...". You cannot only change the text but also stretch and possibly rearrange the button to fit the additional 6 characters. Without this it would result to parts of the string been hidden or overlap other controls on the dialog/form.
These kind of problems can be solved easily only using dlls. I suppose other ways are more difficult to implement or require more work for both the programmers and the translators.
Sorry for my poor english.
...Plug & Pray...
|
|
|
|
|
That is absolutely right!
For simple translations, you can use text files or xml files or things like that. But when you are going to translate to so many different applications, you need to change the size of the text boxes as well.
Therefore, I am going to implement some functions that can load toolbars and dialogs. However, I have to check if this is not coming too close to existing functions because then it would be a waste of time.
Best regards,
Geert
Want to spread the newest version of your software automatically? Use Updater!
Visit my website: http://geert.yoki.org
|
|
|
|
|
Here is another approach:
Multiple language support for MFC applications with extension DLL[^]
This is DLL approach. Translater using only *.rc and res\*.* file to make resource-only DLL file for a new language.
Only problem with that approach, you cannot change language on-the-fly, you have to exit your application and launch it again.
I think, personally, for web applicaiton, text file, incluing xml file may be better. For Windows application, language resource-only DLL is a better direction.
---
Herbert Yu
Are you sure the speed of computer industry is proper? Are you sure the software you released is a bug free one?
|
|
|
|
|
i'm quite interested in the XML way
|
|
|
|
|
Several problems here:
> None of the articles I found provided this."
What about this:
http://www.microsoft.com/globaldev/getwr/steps/wrg_mui.mspx
http://www.microsoft.com/globaldev/handson/dev/muiapp.mspx
And, in general, http://www.microsoft.com/globaldev is a very good starting point
> Some people are still hard-coding the strings of their application in their code.
and a bit below
> const CString LNG_DEFAULT = "english";
This is just another form of hard-coding.
Better ways would be to:
- allow the user to configure this.
- pop a dialog with the list of available languages if the desired one is missing
> if (!pLanguage->LoadLanguage(GetSystemDefaultLangID()))
Quote from the MSDN documentation: "The GetSystemDefaultLangID function retrieves the language identifier of the system locale"
What you want is "GetUserDefaultUILanguage"
See here why: http://www.microsoft.com/globaldev/reference/localetable.mspx
The whole idea of the article is not very useful. Instead of carrying around the handle to the resource DLL, so that you can use it with GetString, we now have to carry a CLanguage pointer:
> pLanguage->GetString(IDS_MYSTATICTEXT)
Since you use MFC, you have two main options:
- use AfxSetResourceHandle, and you need no other changes to your code.
- do nothing
Right, "do nothing" is a real option if you use MFC7x
Because deep in the MFC code there is something that gets (correctly) the UI language of the OS, then searches for a resource dll named <appname>.<3charLangCode>
So, if you application is named HelloWorld.exe, drop in the same folder localized DLLs named DEU (German), FRA (France), JPN (Japanese) and so on. On a French system is going to load the resources from the French DLL and so on.
The 3 characters abbreviation is the value returned by GetLocaleInfo with the LOCALE_SABBREVLANGNAME flag.
Try it. It just works, no need for code changes. You might even localize 3rd party applications (if they where developed with MFC7x).
> Language DLL ID Code Language description
> czech.dll 0x0405 CSY Czech
And
> you can edit these settings yourself in Language.cpp
This is more hard-coded stuff.
And the approach restricts you to one module only.
If you have several localizable modules, you are out of luck, you can only have one dll per language.
MS approach for Windows and Office MUI (Multilingual User Interface):
MyApp.exe
Module.dll
PlugIn.dll
<MUI>
<0409>
MyApp.dll
Module.dll
PlugIn.dll
<040c>
MyApp.dll
Module.dll
PlugIn.dll
Now, don't get me wrong, the article tries to solve a real problem, and it does it almost ok.
As a student project is not bad. But the bad part is recommending this in a place like CodeProject, to be used "for real".
The problem was solved before, and better. Just spending a bit more time on the Internet searching for previous ideas always helps.
|
|
|
|
|
> Some people are still hard-coding the strings of their application in their code.
and a bit below
> const CString LNG_DEFAULT = "english";
This is just another form of hard-coding.
>> Better ways would be to:
>> - allow the user to configure this.
>> - pop a dialog with the list of available languages if the desired one is missing
Yes, but this is to configure the class for your application. Of course this is hard-coded.
You are always able to change this to your needs as a software engineer. You can list
the language themselves if LoadLanguage returns false! It's not my task to obligate the
programmer to use my dialogs.
>> Quote from the MSDN documentation: "The GetSystemDefaultLangID function retrieves the language identifier of the system locale"
>> What you want is "GetUserDefaultUILanguage"
Because this is just an example, this is really not important. It is just to show the
class can work with language id's. You aren't going to use this code because it is not
part of the class itself.
>> Since you use MFC, you have two main options:
>> - use AfxSetResourceHandle, and you need no other changes to your code.
>> - do nothing
But there is also a non-MFC class supported. And the AfxSetResourceHandle needs all
the resources to be in the new resource file.
BTW, thanks for all the tips, I will try to search for other articles to write...
BTW2, it's a pitty you have written the message anonymous. I would like to see your articles and maybe they can inspire me to write other/better articles.
Geert
Want to spread the newest version of your software automatically? Use Updater!
Visit my website: http://geert.yoki.org
|
|
|
|
|
In MFC usage of AfxSetResourceHandle is wrong way.
If you have the application with some resource DLL, u can load needed resource DLL and set resource app handle in app' InitInstance to it.
But if you also have another DLL which has own resource DLLs and trying to use AfxSetResourceHandle in dll, you set main app resorce handle instead dll resource handle.
In this case using MFC AfxFindResourceHandle is right way.
It find resource in ALL DLL loaded to main app and to app' dll (resource, system and your own statically and dynamically linked). You also can using resource of one DLL or main app in another DLL without loading it again.
Also you can use my implementation FindResourceHandleLang (class CLanguageTools) - it's simply code copy of MFC AfxFindResourceHandle, that support find resource by language.
ps - sorry for my english
|
|
|
|
|
Hi,
Me again (the "Anonymous").
I am sorry, it was not my intent to do that. In fact, I am quite sure I have typed a name (but not an address). And I know I was not logged-in (could not find the password
I will start with some minor comments, then and then some blah-blah
==============
>> Yes, but this is to configure the class for your application.
>> Of course this is hard-coded.
Well, it is not of-course. The flexibility to change should be at the user level, not programmer level.
Scenario: Belgium. You try Dutch, not found, defaults to French (configurable as fallback by the sys-admin)
The real "hard-fallback" is usualy done by having the fallback language in the main executable.
==============
>> Because this is just an example, this is really not important.
...
>>You aren't going to use this code because it is not part of the class itself.
This is the theory. The practice is that if you provide a nice example, other
will copy-paste and start from there.
The only excuse of not doing it right is if it does hide the point you are trying to make. Example: complete error checking in code trying to show something else. But even then I would add a big comment in the code!
Sure, this is not mandatory, but is based on experience
==============
>> But there is also a non-MFC class supported.
>> And the AfxSetResourceHandle needs all the resources to be in the new resource file.
Correct.
==============
>> BTW2, it's a pitty you have written the message anonymous. I would like to
>> see your articles and maybe they can inspire me to write other/better
>> articles.
My name is Mihai Nita (just in case CodeProject displays only the nick), worked in localization / internationalization for the last 8 years.
MS Windows SDK MVP, in fact, Internationalization MVP. There is no such title, they squized me where in the closes drawer , but you can see it here:
http://blogs.msdn.com/michkap/archive/2005/06/01/424067.aspx
You can find me almost every day (night, California time) answering i18n questions, mostly on microsoft.public.win32.programmer.international
You can probably find most of my older answers with Google (search Groups for author:mihai author:n)
I am kind of lazzy, so I cannot point you to a web site (at least not for now But I am working on it.
======= Now, the blah-blah =======
Now, enough about me.
I have read again my post, it seems nastier than intended. Sorry.
English is not my language and I don't like reading twice befor posting.
Overall you did quite nice. I have seen way worse in production applications.
The lack of i18n awareness is amazing sometimes.
Keep up the good work, and (maybe) keep in touch,
Mihai
|
|
|
|
|
well, I think you are right about the constants. I changed them to member variables which can be changed using an Init function. I will upload the new version today (but CP will take a few days to review the article).
I am going to try and expand this class so it can load multiple dll's, toolsbars and dialogs.
I also removed the library dependency by using the file as Blake Miller suggested.
And I know not all articles can be used in real-life. But most programmers here also want to develop applications in their free time. For them, this is an easy solution to support multiple languages.
Because most things here can only be used for non-commercial apps, I think this site is not only for professional developers.
Geert
Want to spread the newest version of your software automatically? Use Updater!
Visit my website: http://geert.yoki.org
|
|
|
|
|
Right, "do nothing" is a real option if you use MFC7x
Because deep in the MFC code there is something that gets (correctly) the UI language of the OS, then searches for a resource dll named .<3charLangCode>
I could have sworn that MFC with Visual Studio 6.0 did this as well, but I could not find the code. I am almost certain that the older verisons of MFC DID do this, then MS must have removed it for some reason, and now it is back in again. Very strange.
|
|
|
|
|
Well Said Mihai...
Nat pear
|
|
|
|
|
|