Archive: LangString question about ${Default} usage


LangString question about ${Default} usage
I've inherited a few NSI scripts and have a question about a LangString feature. In these scripts they use something like:

LangString FOO ${Default} "hello world"

They have this in blocks where we may have translations for 4-5 langs. The theory being that if you're on an OS other than the 4-5 specifically called out, this string will display. However in practice this doesn't appear to work. A partner ran a setup on a Russian OS and one of the message boxes comes up with no text, despite having this default string. I'm getting some non-English systems setup to test this.

I can't find any reference to it in the languages.nsi or on the forums. Was someone smokin' crack when they wrote this? :-) or is it supported in some version of NSIS? We're on v. 2.15.

What is the best practice for the situation where you may end up on a uncommon OS, but don't want to localize everying into all possible langs?

Cheers!


Common practice is to set up english as default language.
Obviously the ${Default} you're referring is a definition which needs a value, you may want to take a look at NSIS manual about !define.


Right, the intention is to use English as the default and I know how to use !define - I may not know how the lang tables work however!

I guess my question is on the functionality of LangString. Is 'Default' a magic term? If I define Default = LANG_ENGLISH, is there logic at run-time that chooses that LangString definition if I'm on a French OS (example below)?

LangString FOO ${LANG_ENGLISH} "test"
LangString FOO ${LANG_GERMAN} "German test"
LangString FOO ${Default} "test"

LangString BAR ${LANG_ENGLISH} "test2"
LangString BAR ${LANG_GERMAN} "German test2"
LangString BAR ${Default} "test2"

The LangString docs say to set a string for every lang in your script, which implies (to me anyway) that there is no overriding 'default' string feature where if NSI can't find the defined OS string it will look for a default one to fall back on.

Am I making any sense? :-)

Thanks much....


Unable to have an opinion why somebody has used that ${Default} definition and what he was trying to manage unless there is the ability to review the script.
However requesting a multi lang installer all it needs is to follow the included examples I guess.


Thanks Red Wine. I've attached a very simplified script which hopefully illustrates the basics of what this script was intended to do.

It appears the intent was that if it were run on a lang where a string wasn't specifically defined that the 'default' would take over for any string block. In the original scripts there are mutiple string blocks which all have a 'default' value (like my posted example). The attached script just has one block to illustrate the point.

The behavior of the script is that say on a Russian OS, the message box contents are blank vs having an English default. This is based on screen shots from our parter who is running these tests.

Am I correct in the assumption that this implied 'default' processing is not a feature in NSI?

Thanks!


As already mentioned, you don't really need something like this.
Using the select language dialog as presented in the included examples is the right way to go, users are able to select installation's language from dropdown menu.
Even if for some reason you don't wish to add that dialog, by adding English language 1st in the sequence of the included languages preserves that on a target where the local settings do not much any of the included languages, NSIS chooses English automatically.


Originally posted by Red Wine
As already mentioned, you don't really need something like this.
Using the select language dialog as presented in the included examples is the right way to go, users are able to select installation's language from dropdown menu.
Even if for some reason you don't wish to add that dialog, by adding English language 1st in the sequence of the included languages preserves that on a target where the local settings do not much any of the included languages, NSIS chooses English automatically.
I'm having similar problems as the OP is, but I'm not doing anything weird with a "Default" language or anything.

I've modified the example script to simplify it and remove the default stuff. The basic problem is that $(TEST_STRING) is empty for the Spanish translation (where there is no explicit translation), when I'd like it to use the English default.

Any ideas?

Originally posted by datallah
I'm having similar problems as the OP is, but I'm not doing anything weird with a "Default" language or anything.

I've modified the example script to simplify it and remove the default stuff. The basic problem is that $(TEST_STRING) is empty for the Spanish translation (where there is no explicit translation), when I'd like it to use the English default.

Any ideas?
I am having the exact same issue.
When the translation is incomplete the missing strings are replaced by empty strings.

Instead of that i would like to use their english version.

I store the langvars strings in seperate .nsh files. The compiler gives me a warning for every missing string.

Is there a way to force the use of the default language strings when the translated version is missing ?

You'll just have to add the individual language strings but to avoid having repetitions of the string itself, use a define.

Stu


Can you elaborate a bit ?
I would like to use the english version of $(message) when it is missing in one language.

What is the syntax to use define with a langvar ?

Here is my problem :
1- I can not use LangVar inside of sections and functions.
2- I can not read the content of $(message) outside sections and functions.
3- $language is not set before the end of .oninit.

So, once $language is set, i can test if $(message) is empty, but then it's too late to use LangVar and set the content of $(message).


Here is a sample based on the sample.nsi three posts up :


LangString TEST_STRING ${LANG_ENGLISH} "English String"
LangString TEST_STRING ${LANG_GERMAN} "German String"
LangString TEST_STRING ${LANG_FRENCH} "French String"
### Missing Spanish String here #########


The following does not work :
-outside sections and functions, $(TEST_STRING) is not yet initialised. That is quite normal since $language is not set.
-inside sections and functions, you can't use langstring.


!ifndef $(TEST_STRING)
LangString TEST_STRING $language "English String"
!endif


Is there a macro to define $(TEST_STRING) without using LangString ?
Is there a macro to access the contents of the language table without using the $(...) syntax ?

@ datallah + @ ecology2007,

Sorry I can't get your point guys, setting every language string explicitly for every included language is a requirement in order for a proper functionality.
If for some reason one wants to skip a string for one or more included languages then a definition should take place e.g.

!define MULTILANG_MSG "A message showing for a couple of languages"

LangString TEST_STRING ${LANG_ENGLISH} "English String"
LangString TEST_STRING ${LANG_GERMAN} "German String"
LangString TEST_STRING ${LANG_FRENCH} "French String"

LangString TEST_STRING ${LANG_SPANISH} "${MULTILANG_MSG}"


Originally posted by Red Wine
@ datallah + @ ecology2007,

Sorry I can't get your point guys, setting every language string explicitly for every included language is a requirement in order for a proper functionality.
If for some reason one wants to skip a string for one or more included languages then a definition should take place e.g.

!define MULTILANG_MSG "A message showing for a couple of languages"

LangString TEST_STRING ${LANG_ENGLISH} "English String"
LangString TEST_STRING ${LANG_GERMAN} "German String"
LangString TEST_STRING ${LANG_FRENCH} "French String"

LangString TEST_STRING ${LANG_SPANISH} "${MULTILANG_MSG}"
This really doesn't sound reasonable to me.

If this really is the case, there should be a compile time error for missing translations because it effectively makes the installer unusable for these users.

I'm sure I can hack together a macro to make it use the default language, but it seems crazy that this wouldn't be built in functionality.

Modifying your posted sample.nsi, does not produce any kind of compiler error,

!define MULTILANG_MSG "A message showing for a couple of languages"

;--------------------------------
;Include Modern UI

!include "MUI.nsh"

;--------------------------------
;General

Name "Test"
OutFile "testinst.exe"
InstallDir "C:\Program files\Test"

SetCompressor /SOLID lzma

;--------------------------------
;Pages

!define AppTitle "Test app"

!define MUI_HEADERIMAGE
!define MUI_WELCOMEPAGE_TITLE_3LINES
!define MUI_FINISHPAGE_TITLE_3LINES
!define MUI_ABORTWARNING
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH

!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_FINISH

;--------------------------------
;Languages
!insertmacro MUI_LANGUAGE "English"
!insertmacro MUI_LANGUAGE "French"
!insertmacro MUI_LANGUAGE "German"
!insertmacro MUI_LANGUAGE "Spanish"

;--------------------------------


LangString TEST_STRING ${LANG_ENGLISH} "English String"
LangString TEST_STRING ${LANG_GERMAN} "German String"
LangString TEST_STRING ${LANG_FRENCH} "French String"

LangString TEST_STRING ${LANG_SPANISH} "${MULTILANG_MSG}"

Function .onInit

!insertmacro MUI_LANGDLL_DISPLAY

FunctionEnd

;Installer Sections

Section "${AppTitle}" SecStarted

SetOutPath "$INSTDIR"
File sample.nsi

MessageBox MB_DEFBUTTON2|MB_YESNO $(TEST_STRING) /SD IDYES IDYES true IDNO false
true:
false:
;Create uninstaller
WriteUninstaller "$INSTDIR\Uninstall.exe"

SectionEnd

;--------------------------------
;Uninstaller Section

Section "Uninstall"

Delete "$INSTDIR\sample.nsi"
Delete "$INSTDIR\Uninstall.exe"
RMDir "$INSTDIR"

SectionEnd

I see your point, datallah, there should be a compile time error or at least a warning if a language is included but no LangString is specified for that included language when used.

However, it is up to the programmer to check that everything works. It'd be plain lazy not to hard code language strings for all included languages.

Stu


Originally posted by Afrow UK
I see your point, datallah, there should be a compile time error or at least a warning if a language is included but no LangString is specified for that included language when used.

However, it is up to the programmer to check that everything works. It'd be plain lazy not to hard code language strings for all included languages.

Stu
There is a warning about the missing translation, I just didn't realize that it meant that the text would be missing.

I was mistakenly assuming that it'd work similar to how gettext works (where the default value is used if there is no available translation).

Laziness isn't really the reason for my not adding the defaults - If I stifle the warning by adding the English text to the translations, I will no longer be able to use the warning to tell the translators which strings are missing (Unfortunately, I can't expect them to fix the translations in a timely manner (or sometimes at all)).

Perhaps the docs should be clarified to indicate that an undefined LangString for a language will result in missing text - I suspect that I'm not the only person that was confused about how it works.