Archive: suggestions for translations/scripting


suggestions for translations/scripting
Hi,

I just downloaded NSIS and when I took a look at the scripting language it almost looked to me like FORTH (except that NSIS doesn't use RPN). Why not just using FORTH or LISP (or something similar) instead of something new?

However, it also seems that Providing translations for the installer is quite difficult. What about a solution similar to GNU gettext.

Example (FORTH notation):
"This is the text to translate" gettext MB_OK MessageBox

Example with "domain":
"This is a text used inside the MUI package" "MUI" dgettext MB_OK MessageBox

The "gettext" / "dgettext" functions automatically try to translate the text on the stack to the current system/user language.

You can get the current user language ID with the following snippet:

// --- snip ------------------------------------
#include <windows.h>

std::string GetLanguageId(void)
{
std::string LanguageId = GetLocaleStr(LOCALE_USER_DEFAULT, LOCALE_SABBREVLANGNAME, "");
std::string GnuBasicLanguageId = ((LanguageId.size()==0) ? std::string() : LanguageId.substr(0, 2));
return GnuBasicLanguageId;
}
// --- snip ------------------------------------

Regards,
mjs


What's wrong with the current system with language files and language strings?


For GNU gettext you also need language files, but the great advantage is its ease of use. Instead of having something like:

if (language=="de") {
ShowText("Alles OK");
} else {
ShowText("Everything's OK");
}

You can simply use:

ShowText(gettext("Everything's OK"));

gettext knows the current language ID and searches for a translation for this string in the current domain - or in another domain when you use dgettext instead.

There is no need for different include files that define texts in a different way depending on the wanted target language. Instead you have a single source file and just deploy several translation files containing the translations for all texts needed in the application.

GNU gettext automatically chooses the correct language file depending on the contents of the environment variable LANGUAGE. When it cannot find a translation, it simply returns the string that was passed to the gettext or dgettext function.

I use this library in many applications (even though Borland C++ builder supports ressource DLLs for translations but they don't work well when the GUI changes constantly) and it is very easy to use.

However, it might be fine to have a similar (not the same, because it doesn't fit into the current scripting language because it doesn't support function calls in arguments) mechanism in NSIS.

The advantages are - in short terms:
1. ease of use
2. it's easy to add new translations


This is the way it's working now. I don't see why this library can be of any use. You are talking about NSIS 2, right?


I think you are talking about NSIS 1.x. NSIS 2 (http://nsis.sf.net) has language files that can be translated and language strings that can be used in multilingual scripts.


In the documentation of NSIS2, I found the following section:

--- snip ---
LangString message ${LANG_ENGLISH} "English message"
LangString message ${LANG_FRENCH} "French message"
LangString message ${LANG_KOREAN} "Korean message"

MessageBox MB_OK $(message)
--- snip ---

which is just a shortcut for something similar to

--- snip ---
StrCmp $LANGUAGE ${LANG_ENGLISH} 0 +2
StrCpy $R0 "English message"
StrCmp $LANGUAGE ${LANG_FRENCH} 0 +2
StrCpy $R0 "French message"
StrCmp $LANGUAGE ${LANG_KOREAN} 0 +2
StrCpy $R0 "Korean message"

MessageBox MB_OK $R0
--- snip ---

What I meant was:

--- snip ---
MessageBox(MB_OK , gettext("English message"))
--- snip ---

where the "English message" will be used as a look-up key for the wanted translated message or - if none was found - the unchanged english message.


It's not a shortcut for a big switch, it really does get the local language (unless the user chose another one or changed by the script), and according to it chooses the right language table and then uses an offset to get the real string. There are no huge switches here. The only difference I can see is that gettext have a default string.

Creating language files for your installer isn't really that hard. Have a look at the Miranda installer for example.


OK, I think I see where you're getting at. The current translation method looks good enough for me. Optional external language files for the installer will not be added before NSIS 2 final.

And the Miranda installer shows you how to use external (non-optional or runtime) language files.


Hmmm ... maybe I am not able to express what I mean.

The current multilanguage support has several drawbacks:

1. What about different character sets (kanji, turkish, ...)? It doesn't look like you're using UTF8 in the NSIS sources.
2. You have to change the script file if you want to add another language.
3. The user has to use IDs in his scripts and this is IMHO not intuitive.
4. No automatic extraction of the texts that have to be translated.
5. No default text if the user forgot to translate a message.

As I previously wrote, it's much more comfortable to just write something like gettext("text to translate") instead of defining an ID and assigning a correct translation to this ID.


NSIS supports MBCS for languages with another character set (there are Chinese, Korean, Japanese etc. translations). It does not support Unicode because that is not supported on Windows 95/98/ME.

You can keep your translations separate from the script, just use header files for the translations.


With your method you have to change the script too, you have to add gettext, which doesn't really fit well into the current script language structure. I'd even say it breaks it.

With your method the user will have to create a file named or with a header containg the language name. The same goes for the current method, just include the name of the language (${LANG_ENGLISH}), or if you want you can define a value at the top of the included file and use a macro that automatically appends that language ID (Miranda and MUI for example).

The texts are automatically translated, all the user needs to know is the name of the language string.

Again, the only difference I see is the default string.


Interesting that I discorered this thread. Using gettext suite of tools it by far the best translation method I ever used. Now I'm forced to create import/export scripts for the conversion like nsi2po and po2nsi.

If someone wonders why is seams that it doesn't have real like experience with this kind of job and how can be managed well. Is't so easy to work with po files and there are a lot of editors - plus when the strings are added/modified/removed you don't have to deal with manual file sincronization.