Hi,
I have a solution to let user select the perferred language during application startup, but it is not perfect.
Step 1: At the very beginning of the application startup we show a global list query to offer a list of supported languages for the user, and then we remember the user choice in some way.
Code:
// begin by chen
...
#include <badesca.h>
#include <akngloballistquery.h>
#include <e32property.h>
void MainL()
{
_LIT(KPhoneLanugage, "Phone language");
_LIT(KEnglish, "English");
_LIT(KChinese, "Chinese");
CDesCArray* array = new(ELeave) CDesCArrayFlat(5);
CleanupStack::PushL(array);
array->AppendL(KPhoneLanugage);
array->AppendL(KEnglish);
array->AppendL(KChinese);
// the application framework has not be created yet so we the notifier service to show the list
CAknGlobalListQuery* query = CAknGlobalListQuery::NewLC();
TRequestStatus status = KRequestPending;
query->ShowListQueryL(array, status);
User::WaitForRequest(status);
TInt ret = status.Int();
if(ret>=0)
{
// ret is the index of the user selected item
// here we map the user selection to a language code
TLanguage language = ELangEnglish;
switch(ret)
{
case 0:
{
language = User::Language();
break;
}
case 1:
{
language = ELangEnglish;
break;
}
case 2:
{
language = ELangPrcChinese;
break;
}
default:
{
language = User::Language();
break;
}
}
// here we define a property to hold the user selection, but this is definitely not the only way, for example you can also save it to a file.
RProperty::Define(KUidUrzpvtchApplication, 0, RProperty::EInt);
RProperty::Set(KUidUrzpvtchApplication, 0, (TInt)language);
}
CleanupStack::PopAndDestroy(2, array);
}
GLDEF_C TInt E32Main()
{
// begin by chen
// at this stage we have to create the cleanup stack by ourself
// Cleanup stack needed
CTrapCleanup* cleanup = CTrapCleanup::New();
if(cleanup)
{
TRAPD(err, MainL());
if(err != KErrNone)
{
_LIT(KUserPanic,"Failed to start");
User::Panic(KUserPanic, err);
}
delete cleanup;
}
// end by chen
return EikStart::RunApplication( NewApplication );
}
Step 2: During application framework initialization we replace the default resource file with the one selected by the user
The application's resource file can be changed from the default by overriding ResourceFileName(), see below.
Code:
#include <coeutils.h>
...
TFileName CUrzpvtchApplication::ResourceFileName() const
{
TFileName filename = CAknApplication::ResourceFileName();
TInt language = 0;
TInt err = RProperty::Get(KUidUrzpvtchApplication, 0, language);
if(err==KErrNone)
{
TFileName fn = filename;
_LIT(KExtFormat, "r%d");
TBuf<16> buf;
buf.Format(KExtFormat, language);
if(buf.Length()<=2) // for example "r1"
{
_LIT(KZero, "0");
buf.Insert(1, KZero); // now should be "r01"
}
TInt pos = fn.LocateReverse('.');
fn.SetLength(pos+1); // remove the extention
fn.Append(buf); // add new extention
// make sure that the filename actually exists, or there will be a User 23 panic
TBool exists = ConeUtils::FileExists(fn);
if(exists)
{
filename=fn;
}
}
return filename;
}
Note:
1. The title will not be changed because it is defined in _reg.rsc, so you have to update it programically according to the user selection.
2. The system-wide strings like CBA "Options" will not be changed because they are defined in the S60 system resource file instead of the application's resource file.
Regards
Ziteng Chen