localization, windows phone, wp7dev, wpdev

In the Spirit of Open Source…

I have been asked multiple times to Open Source my Localization Tool and I always wanted to do so. But somehow I did not find the time for Code Cleanup, setting up Github and so on. Even now I´m not Open sourcing it directly and I don´t even know if that would be helpful to anybody. But I´m showing you parts of the Code and explain how it works.

2015-12-23

What this Tool does in the first step is to take some Strings and translate them to a bunch of languages. I never updated the Tool to the latest Windows Phone Versions so some supported languages are not in the Tool.

I use the Microsoft Translator Online Service with its SOAP API for the translation process. All you need is to register your Application to get an authorized AppID to access the Online Service. The API itself is very simple, especially in the use case of our little Tool.

I just call something like:

string strTranslated = translator.Translate(„APPID„, textBoxEnglish1.Text, „en„, „de„);
textBoxGerman1.Text = strTranslated;
strTranslated = translator.Translate(„APPID„, textBoxEnglish2.Text, „en„, „de„);
textBoxGerman2.Text = strTranslated;

Imagine that repeated for all other available languages. The Online Translator Services supports a lot of the languages but not all. So i just copied the English Text to those Text fields directly.

That´s all I had to do for the basic translation and this was already the complete first step in the tool. The next step was up to the user who now could freely edit the strings and fine tune the translation. The next and final Step was to Save those strings to the corresponding resource DLLs. That was the more complex part but it used very old and long existing technics and APIs. To be honest I just grabbed some sample Code from MSDN and adjusted it to my needs.

The download of the Tool contained already an AppResLib.dll.  What I now had to do was to copy that DLL to a new file with a language ID and MUI extension.

That looked like:

//Neutral
System.IO.File.Copy(Application.StartupPath + „\\DLLs\\AppResLib.dll„, fbd.SelectedPath + „\\AppResLib.dll„, true);
//EN-US
System.IO.File.Copy(Application.StartupPath + „\\DLLs\\AppResLib.dll„, fbd.SelectedPath + „\\AppResLib.dll.0409.mui„, true);
//EN-UK
System.IO.File.Copy(Application.StartupPath + „\\DLLs\\AppResLib.dll„, fbd.SelectedPath + „\\AppResLib.dll.0809.mui„, true);

After that happened for all languages I only had to replace both String resources within those DLLs with the translated strings from the UI fields. I therefore created a native C++ DLL that exported two functions:

UpdateAppTitle & UpdateAppTitleString

I just include one of those functions for example here and explain it. The second function is more or less the same. Only the padding where to put the string is different.

That´s how the function looks:

WP7DLLUPDATERDLL_API int UpdateAppTitle(LPCWSTR strDLL,LPCWSTR strString)
{
HANDLE hUpdateRes = NULL;
BOOL result = FALSE;
LPVOID    pRes;
DWORD dwBlockSize = 16*sizeof(WCHAR);
DWORD dwReturn = 0;

hUpdateRes = BeginUpdateResource(strDLL, FALSE);
if(hUpdateRes != NULL)
{
dwBlockSize += wcslen(strString)*sizeof(WCHAR);
pRes = malloc(dwBlockSize);
WCHAR*    pParse = (WCHAR *)pRes;
*pParse++ = 0;
*pParse++ = 0;
*pParse++ = 0;
*pParse++ = 0;
int nLen = 0;
*pParse++ = nLen = wcslen(strString);
for(int i = 0;i<nLen;i++)
*pParse++ = strString[i];
*pParse++ = 0;
*pParse++ = 0;
*pParse++ = 0;
*pParse++ = 0;
*pParse++ = 0;
*pParse++ = 0;
*pParse++ = 0;
*pParse++ = 0;
*pParse++ = 0;
*pParse++ = 0;
*pParse++ = 0;

if(UpdateResource(hUpdateRes,RT_STRING,MAKEINTRESOURCE(7), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),pRes,dwBlockSize))
{
if(EndUpdateResource(hUpdateRes, FALSE))
dwReturn = 0;
else
dwReturn = GetLastError();
}
else
dwReturn = GetLastError();
}
else
dwReturn = GetLastError();
return dwReturn;
}

The function takes the String that has to be replaced and the DLL where it has to be replaced as a parameter and uses the UpdateResource API to do the actual work. Very easy and not complex even if the above code looks strange at first.  But how does it work in detail?

String resources in native DLLs come in Blocks containing 16 Strings. We need to update the string with the ID 100 for the App Title.  As those String (Or resource) IDs begin with 1 we need to Update the fifth string in the seventh Block. That is what those “*pParse++ = 0;” do. Set the string to 0. For the fifth string we first write the length of the string and afterwards the string itself to the Memory containing the Ressource Block. Within the UpdateResource API call we tell the API which Block to update . That´s the “MAKEINTRESOURCE(7)” parameter. After the call to EndUpdateResource the DLL contains the new string and based on the filename it can be used for the App Tile Strings. Interestingly this works just fine with the DLL Resource language set to English (US). It just depends on Filenaming conventions.

– Patrick

App Hub, Dev Center, Marketplace, Windows Phone 7, wp7dev, wpdev

„Update selected“ oder „Add new“

Im neuen Dev Center hat sich einiges gegenüber dem bisherigen App Hub Portal geändert. Es werden jetzt eine ganze Menge mehr Optionen geboten und viele Aufgaben lassen sich jetzt  schneller oder erst überhaupt durchführen. Eine etwas verwirrende neue Funktion findet sich im Update Bereich wieder, wenn man seine App aktualisieren möchte. An der Stelle wo man das XAP Paket bereitstellt findet man nun mehrere Menüpunkte:

Wo ist nun also der Unterschied zwischen „Update selected“ und „Add new“? „Update selected“ entspricht dem bisherigen Verfahren zur Aktualisierung eines XAP Files. Also neue Version hochladen, Test abwarten und publizieren. Alles wie gehabt. Die Funktion „Add new“ erlaubt es jetzt aber ein zusätzliches XAP File hochzuladen, welches zwar die gleich App beinhaltet, sich aber von dem anderen XAP File unterscheiden kann (sogar muss). Wozu ist das jedoch gut?

Ganz einfach, man kann nun mit ein und derselben App (Im Dev Center, aber auch für den Anwender) unterschiedliche Betriebssysteme, Hardwaretypen oder Sprachvarianten unterstützen.

So kann man beispielsweise ein XAP File für Windows Phone 7.0 beibehalten, aber gleichzeitig auch ein Update für Windows Phone 7.5 Anwender bereitstellen.

Ein weiteres Beispiel wäre die Verwendung der Frontkamera, bei der es sich um optionale Hardware handelt.

Oder aber die Unterstützung anderer Sprachen die gegebenenfalls eine andere  Schreibrichtung benötigen, und somit ein anderes UI Design erfordern können.

Sobald die Publizierung wieder läuft werde ich die Funktion mal austesten.

– Patrick

Allgemein, Tips & Tricks, wp7dev, wpdev

Fehlende Capabilities: Copy & Paste

Öffnet man ein Projekt indem keine Capabilities in der WMAppManifest vorhanden sind erhält man unter Umständen zur Begrüßung oder bei einem Upgrade auf Windows Phone 7.1 folgende Meldung:

Wer jetzt einen Screenshot davon erstellt und später fleißig abtippt kennt anscheinend eine grundlegende Funktion einer MessageBox nicht. Copy & Paste Unterstützung. Einfach STRG+C drücken und schon kann man den Inhalt der Meldung woanders per STRG+V wieder einfügen.

Hätte ich für jeden Screenshot einer MessageBox (Im Regelfall der ganze Desktop, eingebettet in ein WORD Dokument) den ich per Mail bekommen habe einen €uro erhalten, könnte ich eine ganze Armee von Ghostwritern für diesen Blog beschäftigen :-).

– Patrick

Allgemein, Windows Phone 7, wp7dev

Kontaktbilder

Windows Phone 7.5 bietet ja nun die Möglichkeit über die Contacts Klasse auf die Kontakte zuzugreifen. Für einen speziellen Anwendungsfall wollte ich jedoch nur Kontakte anzeigen, die ein „gültiges“ Profilbild besitzen. Ein dementsprechendes Suchkriterium gibt es derzeit nicht, aber eigentlich sollte der Rückgabewert von Contact.GetPicture() ja null sein, wenn der Kontakt kein Bild besitzt. Leider machte mir an dieser Stelle Facebook einen Strich durch die Rechnung, da es für den Fall der Fälle* Standardbilder verwendet, welche dann auch auf das Windows Phone synchronisiert werden. Bisher wüsste ich allerdings nur von einem Standardbild pro Geschlecht, also ist dies noch relativ überschaubar und dementsprechend einfach mit dem Kontaktbild zu vergleichen. Um mir das Leben zu vereinfachen habe ich eine einfache Extension Methode erstellt, die als Rückgabewert den jeweiligen Bildtypen enthält. Verwendet werden könnte die Methode wie folgt:

void kontakte_SearchCompleted(object sender, ContactsSearchEventArgs e)
{
//Neue Liste erstellen
List<Contact> filter = new List<Contact>();
foreach (Contact con in e.Results)
{
//Erweiterungsmethode
switch(con.GetPictureType())
{
case ContactPictureType.None:
case ContactPictureType.DefaultFemale:
case ContactPictureType.DefaultMale:
default:
break;
case ContactPictureType.Custom:
//Der Liste hinzufügen
filter.Add(con);
break;
}
}
//Datenbindung
listBox1.DataContext = filter;
}

Download der Extension-Methode

– Patrick

* Profile ohne richtiges Profilebild sollten auf Facebook verboten werden

App Hub, Marketplace, Windows Phone 7, wp7dev

App Hub: GeoTrust Verifizierung

Aufgrund der Mango Beta gab es in den letzen Tagen wieder viel Spekulation um die GeoTrust Verifizierung und die Aufschreie wurden lauter das keine Mails von GeoTrust kommen würden.

Wie sich in den diversen Foren herausstellte hatten nahezu alle „Problemfälle“ einen Dreamspark Account.

Daher hier noch mal die Information:

Wenn eine bestehende XNA Creators Club Mitgliedschaft in eine App Hub Mitgliedschaft verwandelt wird muss eine App in den Marketplace eingestellt werden damit GeoTrust einen Verifizierungsauftrag erhält.

Um eine GeoTrust Verifizierung für einen Studentenaccount via Dreamspark zu erhalten gilt auch: Erst eine App in den Marketplace einstellen.

Vorher ist es nicht möglich das Gerät als Entwicklergerät freizuschalten und somit auch nicht möglich die Mango Beta zu installieren.

– Patrick