This type of command line utility is the worst

Over the last few releases, several interesting command line utilities have moved from the res kit into the default Windows installation. For instance, in Windows XP we have Tasklist, Taskkill, Bootcfg and Shutdown. In Server 2003 even more were added, such as Setx, Forfiles and Clip. Handy indeed.

The other day I was whining about localizing command line utilities in general, and netsh in particular - much because of the long strings with embedded formatting. Turns out, netsh syntax messages are nothing but fun compared with the tools I mention above.

Do this:
Open a command prompt window
Type bootcfg /? and press enter

The syntax message you see is not one single string. Nope. What appears as one single message on your screen is actually a bunch of individual strings inside the binary. This is what I have to work with:

 "STR";   10 - Parameter List:\n
"STR";   11 -     /S      system           Specifies the remote system to connect to.\n\n
"STR";   12 -     /U      [domain\\]user    Specifies the user context under which\n
"STR";   13 -                              the command should execute.\n\n
"STR";   14 -     /P      [password]       Specifies the password for the given\n
"STR";   15 -                              user context. Prompts for input if omitted.\n\n
 

Etc.

This is bad for me. I still have the same constraints as before -- row length, formatting, consistency and so on. But on top of this, I have to consider more than one string at a time. At least in netsh, I can localize & forget string by string. Not here. Look at these strings:

 "STR";    8 -     Deletes an existing boot entry in the [operating systems]\n
"STR";    9 -     section of the BOOT.INI file.\n\n
 and
"STR";   16 -     /ID     bootid           Specifies the boot entry id that needs\n
"STR";   17 -                              to be deleted from the [operating systems]\n
"STR";   18 -                              section of the BOOT.INI file.\n\n
 

That the source in 9 and 18 matched is just coincidence. I can't repeat that coincidence and still be happy with my translation. I know this, but my tool doesn't -- and therefore, if I auto translate wildly, I'll end up with messages that are pieced together by random fragments and that simply don't make sense.

Also, let's get back to this part again:

 "STR";   10 - Parameter List:\n
"STR";   11 -     /S      system           Specifies the remote system to connect to.\n\n
"STR";   12 -     /U      [domain\\]user    Specifies the user context under which\n
"STR";   13 -                              the command should execute.\n\n
 

The same strings appear in a lot of these utilities. Here's the same section from Eventcreate.exe:

 "STR"; 1009 -     /S    system           Specifies the remote system to connect to.\n\n
"STR"; 1010 -     /U    [domain\\]user    Specifies the user context under which\n
"STR"; 1011 -                            the command should execute.\n\n
 

See that? Even though the text is identical, the formatting isn't. The lower strings are a little bit farther to the left. Even though they're so similar, if I auto translate wildly I will end up with uglily formatted syntax messages. But if I don't auto translate, I'll have to spend more time trying to get consistent translations.

Another detail to note is that I might not be able to fit the text within 80 chars without adding rows. Luckily, since each string here contains at least one line feed, I can add my own rows where I need to. Here's an example from waitfor.exe where I've done just that:

 "STR"; 2027 -     /T     timeout        Number of seconds to wait for signal. Valid range\n
"STR"; 2028 -                           is 1 - 99999. Default is to wait forever for signal.\n\n
 

becomes

 "STR"; 2027 -     /T     timeout        Antal sekunder att vänta på signalen. Giltiga\n
"STR"; 2028 -                           värden är 1 - 99999. Standard är att vänta i\n                          evighet.\n\n
 

Not pretty, but it works. Similarly, if my translation requires fewer rows than the source, I can simply let a resource become an empty string. Neither of these options is great for future auto translation...

The final problem I have with these utilities in particular is that there's a risk of over translation. If you check the help for getmac.exe, you see that one of the options is this:

 "STR";   23 -     /FO    format            Specifies the format in which the output\n
"STR";   24 -                              is to be displayed.\n
"STR";   25 -                              Valid values: "TABLE", "LIST", "CSV".\n\n
 

Unfortunately, the values for CSV, TABLE and LIST are also in my resources but unless I've seen this string above it's not obvious to me what they do. Far as I know, they could just be text that's displayed to the user. I might therefore translate them, and if I do the syntax message might not match the actual value to use, or scripts may behave differently on different language versions of Windows. This last point is imporant. I can actually break stuff by translating simple words like "table" and "list". Not so good.

So - if you're a developer and you're thinking about writing a command line utility like these ones, please 1) don't mix up formatting and content; 2) don't split sentences across resources and 3) keep non-localizable data hard-coded.