This week I have been searching a lot on localization in NSIS. Normally we just used the standard dialogs with a default language depending on where the cd-rom would be used. If we made a cd-rom for French-speaking part of Belguim, then the language was French. If the cd-rom was for Dutch-speaking part of Belguim, the language was Dutch. So no choice could be made at the beginning. If something wasn't spelled right, we went changing some things in the standard language files in the NSIS folder under Program Files. However, with a new update, these files get overwritten, so don't know how to do this good...
A new application that we are creating requires the choice of multiple languages and custom dialogs that need to be localized. I haven't figured it out all, but I'm getting to know more and more about NSIS. I guess this is a problem with all Open Source projects. The people who are creating the Open Source project are so familiar with the project that they don't seem to be able to explain something on the level of a user who's not constantly working with the technology. Most of those people are not stupid, but most of the times there are no simple tutorials available. As a result, you go and ask the most stupid questions on a forum. But it's only months later that you realize that the question was stupid.

I first tried to get the multiple languages working. The wizard of the NSISEclipsePlugin was usefull, however, this wizard generates a script that is failing on a few issues.

First you need to import the files for the languages you want to include.

CODE:
  1. !insertmacro MUI_LANGUAGE Dutch
  2. !insertmacro MUI_LANGUAGE French
  3. !insertmacro MUI_LANGUAGE English
  4. !insertmacro MUI_LANGUAGE German

It took a while until I realised that inserting a macro basically means that you are inserting code out of a nsh file you previously imported. The macro MUI_LANGUAGE obviously comes out of the MUI.nsh file which was previously imported (!include MUI.nsh). If you open MUI.nsh you'll see

CODE:
  1. !include "${NSISDIR}\Contrib\Modern UI\System.nsh"

If you open System.nsh and search for MUI_LANGUAGE you'll find the macro

CODE:
  1. !macro MUI_LANGUAGE LANGUAGE
  2.  
  3. ;Include a language
  4.  
  5. !verbose push
  6. !verbose ${MUI_VERBOSE}
  7.  
  8. !insertmacro MUI_INSERT
  9.  
  10. LoadLanguageFile "${NSISDIR}\Contrib\Language files\${LANGUAGE}.nlf"
  11. !insertmacro LANGFILE_INCLUDE "${NSISDIR}\Contrib\Language files\${LANGUAGE}.nsh"
  12.  
  13. !ifndef MUI_LANGDLL_LANGUAGES
  14. !define MUI_LANGDLL_LANGUAGES "'${LANGFILE_${LANGUAGE}_NAME}' '${LANG_${LANGUAGE}}' "
  15. !define MUI_LANGDLL_LANGUAGES_CP "'${LANGFILE_${LANGUAGE}_NAME}' '${LANG_${LANGUAGE}}' '${LANG_${LANGUAGE}_CP}' "
  16. !else
  17. !ifdef MUI_LANGDLL_LANGUAGES_TEMP
  18. !undef MUI_LANGDLL_LANGUAGES_TEMP
  19. !endif
  20. !define MUI_LANGDLL_LANGUAGES_TEMP "${MUI_LANGDLL_LANGUAGES}"
  21. !undef MUI_LANGDLL_LANGUAGES
  22.  
  23. !ifdef MUI_LANGDLL_LANGUAGES_CP_TEMP
  24. !undef MUI_LANGDLL_LANGUAGES_CP_TEMP
  25. !endif
  26. !define MUI_LANGDLL_LANGUAGES_CP_TEMP "${MUI_LANGDLL_LANGUAGES_CP}"
  27. !undef MUI_LANGDLL_LANGUAGES_CP
  28.  
  29. !define MUI_LANGDLL_LANGUAGES "'${LANGFILE_${LANGUAGE}_NAME}' '${LANG_${LANGUAGE}}' ${MUI_LANGDLL_LANGUAGES_TEMP}"
  30. !define MUI_LANGDLL_LANGUAGES_CP "'${LANGFILE_${LANGUAGE}_NAME}' '${LANG_${LANGUAGE}}' '${LANG_${LANGUAGE}_CP}' ${MUI_LANGDLL_LANGUAGES_CP_TEMP}"
  31. !endif
  32.  
  33. !verbose pop
  34.  
  35. !macroend

So this block of code is inserted where you had !insertmacro MUI_LANGUAGE Dutch. I haven't gone though this code, but it loads the nlf language file and inserts the nsh language script. It basically means that instead of using the macro's you could just put all of the code in your script, resulting however in a script the size of a book. I haven't had time to figure out how all these variables of several language files are managed and how NSIS knows depending on the chosen language where to look for the correct variables. But I will look into it.

Now, to display the choice of language in the beginning you need to put some defines at the beginning of the script that will be used by some macro's.

CODE:
  1. #Language defines
  2. !define MUI_LANGDLL_REGISTRY_ROOT HKLM
  3. !define MUI_LANGDLL_REGISTRY_KEY ${REGKEY}
  4. !define MUI_LANGDLL_REGISTRY_VALUENAME InstallerLanguage

Then insert the macro

CODE:
  1. # Language macro's
  2. !insertmacro MUI_RESERVEFILE_LANGDLL

This looks like

CODE:
  1. !macro MUI_RESERVEFILE_LANGDLL
  2.  
  3. !verbose push
  4. !verbose ${MUI_VERBOSE}
  5.  
  6. ReserveFile "${NSISDIR}\Plugins\LangDLL.dll"
  7.  
  8. !verbose pop
  9.  
  10. !macroend

Then in the .onInit function we'll insert another macro

CODE:
  1. !insertmacro MUI_LANGDLL_DISPLAY

which looks like

CODE:
  1. !macro MUI_LANGDLL_DISPLAY
  2.  
  3. !verbose push
  4. !verbose ${MUI_VERBOSE}
  5.  
  6. !insertmacro MUI_DEFAULT MUI_LANGDLL_WINDOWTITLE "Installer Language"
  7. !insertmacro MUI_DEFAULT MUI_LANGDLL_INFO "Please select a language."
  8.  
  9. !ifdef MUI_LANGDLL_REGISTRY_ROOT & MUI_LANGDLL_REGISTRY_KEY & MUI_LANGDLL_REGISTRY_VALUENAME
  10.  
  11. ReadRegStr $MUI_TEMP1 "${MUI_LANGDLL_REGISTRY_ROOT}" "${MUI_LANGDLL_REGISTRY_KEY}" "${MUI_LANGDLL_REGISTRY_VALUENAME}"
  12. StrCmp $MUI_TEMP1 "" mui.langdll_show
  13. StrCpy $LANGUAGE $MUI_TEMP1
  14. !ifndef MUI_LANGDLL_ALWAYSSHOW
  15. Goto mui.langdll_done
  16. !endif
  17. mui.langdll_show:
  18.  
  19. !endif
  20.  
  21. !ifdef NSIS_CONFIG_SILENT_SUPPORT
  22. IfSilent mui.langdll_done
  23. !endif
  24.  
  25. !ifdef MUI_LANGDLL_ALLLANGUAGES
  26. LangDLL::LangDialog "${MUI_LANGDLL_WINDOWTITLE}" "${MUI_LANGDLL_INFO}" A ${MUI_LANGDLL_LANGUAGES} ""
  27. !else
  28. LangDLL::LangDialog "${MUI_LANGDLL_WINDOWTITLE}" "${MUI_LANGDLL_INFO}" AC ${MUI_LANGDLL_LANGUAGES_CP} ""
  29. !endif
  30.  
  31. Pop $LANGUAGE
  32. StrCmp $LANGUAGE "cancel" 0 +2
  33. Abort
  34.  
  35. !ifdef NSIS_CONFIG_SILENT_SUPPORT
  36. mui.langdll_done:
  37. !else ifdef MUI_LANGDLL_REGISTRY_ROOT & MUI_LANGDLL_REGISTRY_KEY & MUI_LANGDLL_REGISTRY_VALUENAME
  38. mui.langdll_done:
  39. !endif
  40.  
  41. !verbose pop
  42.  
  43. !macroend

I'll try to explain this more in later posts, but this gives ou an idea what these macro's are. Actually you don't need to know how they work, but if something goes wrong, or if you want to do custom things, it's really necessary to understand some things.