2004.07.06 14:40 "[Tiff] Suggested Patch for libtiff to easify translation using gettext", by Bernd Herd

2004.07.11 11:47 "Re: [Tiff] Suggested Patch for libtiff to easify translation using gettext", by Bernd Herd

I've done some translation of libtiff error and warning messages to german.

extraction of libtiff messages can be done using the following command:

xgettext   -kTIFFError:2   -kTIFFWarning:2 *.c

The resulting messages.po conatains the translatable strings.

However some strings in libtiff are used with small differences depending on the occurence. For example:

"%d: Sample out of range, max %d"
"Sample %d out of range, max %u"
"%lu: Sample out of range, max %lu"
"%u: Sample out of range, max %u"

The attached patch unifies these messages so they will only consume a single translation entry.

Thank you, I have fixed that.

The attached file de.po contains the translation strings for german.

Thanks too, but this is haven't too much usage in libtiff, because gettext library is LGPL licensed, but libtiff is under less restrictive terms.

The library part of gettext is trivial. The GPLed tools are complex, but the piece of gettext that needs to be linked into the application is trivial.

http://www.wxWidget.org/ contains it's own gettext library using a license with less restrictions than LGPL in C++. I've taken a look on how simple it works and write my own simple "gettext" in C within a few hours.

I've reduced this to a minimum and had an implementation of the library part within a few lines. Please find atatched my own simplified gettext library for WIN32 reading Message Catalogs either from a file or from the application ressources. You'll see it is tivial.

I'm willing to offer this work on the libtiff license, but I think it is pointless. It would be good to have libtiff prepared for translation, but the actual gettext implementation does not need to be included into libtiff.

But I think my de.po message table is valuable for the libtiff project, since it takes a lot of people to collect a lot of translations. I'm offering the de.po file for inclusion into the libtiff distribution.

The usualy gettext No-Operation is simething similar to this this:

#ifdef HAVE_LIBINTL
# include <libintl.h>
#else
# define gettext(T) (T)
# define _(T) (T)
#endif

And in tif_win32.c:

<       wvsprintf(szTmp, fmt, ap);
 >      wvsprintf(szTmp, gettext(fmt), ap);

Bernd Herd
        :-)

Herd Software Entwicklung
Bernd Herd
Kettelerstr. 35
68642 Bürstadt
Germany
Tel.: +49-6206-707775, Fax.: +49-6206-707776
http://www.herdsoft.com

/*---------------------------------------------------------------

        D A V I N C I   -       Dipl. Ing. Bernd Herd

                                Grafikimport/Export FIlterbibliothek
                                Kettelerstr. 35
                                68642 B�rstadt
                                Tel./Fax: 06206/707775

        (C) 2004 Bernd Herd

    gettext.c: My own simplified routines to use message catalogs from GNU gettext.

    Code derived from wxWindows 2.2 comming/intl.cpp class unter wxWindows license
    allowing linking of binaries without offering source code.

  ---------------------------------------------------------------*/

#include <windows.h>
#include <stdio.h>
#include "gettext.h"            // Include-Datei zur Verbindung mit Applikation

extern HINSTANCE hLibInstance;


/// Currently active message catalog
static BYTE *pData=NULL;


struct catalogheader
{
  UINT magic;          // offset +00:  magic id
  UINT revision;       //        +04:  revision
  UINT numStrings;     //        +08:  number of strings in the file
  UINT ofsOrigTable;   //        +0C:  start of original string table
  UINT ofsTransTable;  //        +10:  start of translated string table
  UINT nHashSize;      //        +14:  hash table size
  UINT ofsHashTable;   //        +18:  offset of hash table start
};

struct stringentry
{
  UINT nLen;           // length of the string
  UINT ofsString;      // pointer to the string
};


/**
 * Try to find a translation for the given string in the current
 * message catalog.
 */
const char *
gettext(const char *szOrig)
{
  const char *result=NULL;

  if (szOrig != NULL &&
      pData != NULL)
    {
      struct catalogheader *header = (struct catalogheader *) pData;
      struct stringentry *orig_table = (struct stringentry *) (pData + header->ofsOrigTable);
      struct stringentry *trans_table = (struct stringentry *) (pData + header->ofsTransTable);
      UINT bottom = 0;
      UINT top = header->numStrings;
      UINT current;

      while ( bottom < top && result==NULL)
        {
          current = (bottom + top) / 2;
          int res = strcmp(szOrig, pData + orig_table[current].ofsString);
          if ( res < 0 )
            {
              top = current;
            }
          else if ( res > 0 )
            {
              bottom = current + 1;
            }
          else
            {
              // found!
              result = pData + trans_table[ current ].ofsString;
            }
        }
    }

  return result!=NULL ? result : szOrig;
}


/**
 *(try to) load the message catalog with the given file name
 */
#ifdef DAVINCI_PRO
static
void
loadmo_file(const char *filename)
{
  FILE *fin;
  if (NULL != (fin=fopen(filename, "rb")))
    {
      int size;

      fseek(fin, 0, SEEK_END);
      size = ftell(fin);
      fseek(fin, 0, SEEK_SET);

      if (NULL!=(pData = malloc(size)))
        {
          fread(pData, size, 1, fin);
        }

      fclose(fin);
    }
}
#endif



/**
 * (try to) Load a message catalog, either from the program ressources,
 * or from a .mo file.
 *
 * @param lang    Language specifier. See http://support.microsoft.com/default.aspx?scid=kb;en-us;102978
 */
void
loadmo(const char *lang)
{
  HRSRC hrsrc;
  HGLOBAL hg;

  if (NULL!=(hrsrc=FindResource(hLibInstance, lang, "mo")) &&
      NULL!=(hg=LoadResource(hLibInstance, hrsrc)))
    {
      pData = (LPBYTE) LockResource(hg);
    }
#ifdef DAVINCI_PRO
  else
    {
      char filename[MAX_PATH];
      char *p;

      GetModuleFileName(hLibInstance, filename, sizeof(filename)-20);
      p=strrchr(filename, '\\');
      if (p)
        {
          strcpy(p+1, lang);
          strcat(p, ".mo");

          loadmo_file(filename);
        }
    }
#endif
}



static
void
translate_windowtext(HWND hwndControl)
{
  char szText[1000];
  if (GetWindowText(hwndControl, szText, sizeof(szText)))
    {
      const char *translation = gettext(szText);
      if (translation != szText)
        {
          SetWindowText(hwndControl, translation);
        }
    }
}


/**
 * Translate a dialog window.
 *
 * Iterate through all the controls in the dialog and translate
 * using the gettext approach.
 *
 * @param hwndDialog     Window handle of the dialog to be translated
 */
void
translate_dialog(HWND hwndDialog)
{
  HWND hwndControl;

  translate_windowtext(hwndDialog);

  for (hwndControl = GetWindow(hwndDialog, GW_CHILD);
       hwndControl;
       hwndControl = GetWindow(hwndControl, GW_HWNDNEXT))
    {
      translate_windowtext(hwndControl);
    }
}


/*---------------------------------------------------------------

        D A V I N C I   -       Dipl. Ing. Bernd Herd

                                Grafikimport/Export FIlterbibliothek
                                Kettelerstr. 35
                                68642 B�rstadt
                                Tel./Fax: 06206/707775

        (C) 2004 Bernd Herd

    gettext.c: My own simplified routines to use message catalogs from GNU gettext.

    Code derived from wxWindows 2.2 comming/intl.cpp class unter wxWindows license
    allowing linking of binaries without offering source code.

  ---------------------------------------------------------------*/

#ifndef gettext_h
#define gettext_h

#ifdef __cplusplus
extern "C" {
#endif

// Internationalization support
const char *gettext(const char *sz);
void loadmo(const char *filename);
void translate_dialog(HWND hwndDialog);

#define _(T) gettext((T))

#ifdef __cplusplus
}
#endif

#endif