Search code examples
javamingwwindows-7-x64gettextxgettext

gettext under windows 7 for java project returns 'Bad file descriptor'


I'm trying to use gettext in java project to provide translations for different languages.

My workstation runs Windows 7 and so I'd like to be able to go through whole build process on it (including keys generation and translations update - all from gradle script).

However msgfmt tool returns an error: 'Bad file descriptor' without any additional information...

I was not able to find any helpful information over the Internet. Someone had similar problem and guy named Daiki Ueno proposed a patch but I guess it didn't go to official gettext versions since the issue is still present...

See: https://lists.gnu.org/archive/html/bug-gnulib/2013-09/msg00049.html

Steps

create list of java files in the project

dir *.java /s/b > files.txt

create translations directory

mkdir po

creates a pot file that contains all strings in the native language

xgettext -ktrc -ktr -kmarktr -ktrn:1,2 --from-code=utf-8 -o po\keys.pot -f files.txt

replace CHARSET in keys.pot file to correct encoding name 'utf-8'

...manual step...

create translations file with content description

type nul >> po\pl.po & copy po\pl.po +,,
echo msgid "" >> po\pl.po
echo msgstr "" >> po\pl.po
echo "Content-Type: text/plain; charset=UTF-8\n\" >> po\pl.po

merge keys into localized po file

msgmerge -U po\pl.po po\keys.pot

create default ResourceBundle class file << fails with error (see below)

set JAVAC=c:\Java\jdk1.8.0_40\bin\javac.exe
set TMPDIR=c:\temp
msgfmt --verbose -java2 -d src\main\java -r com.haso.Messages  po\keys.pot

I've tried following implementations of gettext:

  • GetGnuWin32-0.6.3
  • MinGW-0.18.3
  • gettext-tool-windows-0.18.3
  • gettext-tool-windows-0.19.4
  • gettext-iconv-windows-0.19.4

first one crashes in Windows 7 64bit

msgfmt from the rest give the following output:

>msgfmt: c:\Java\jdk1.8.0_40\bin\javac.exe subprocess failed: Bad file descriptor

Could anyone help with getting it work?


Solution

  • I was able to find some workaround to my problem since msgfmt downloaded from here generated java sources...

    This solution requires following environmental variables set correctly:

    JAVA_HOME
    CYGWIN_HOME
    GETTEXT_HOME
    

    I created following script run_gettext.sh in subdirectory named gettext in my project root dir:

    #!/bin/bash
    
    cd `$CYGWIN_HOME/bin/pwd.exe`/gettext
    
    set CYGWIN_HOME=%CYGWIN_HOME%
    set GETTEXT_HOME=%GETTEXT_HOME%
    
    $CYGWIN_HOME/bin/rm.exe -fv files.txt
    $CYGWIN_HOME/bin/find.exe ../src/main/java -name *.java > files.txt
    
    $CYGWIN_HOME/bin/mkdir.exe -pv po
    
    $GETTEXT_HOME/xgettext.exe -ktrc -ktr -kmrktr -ktrn:1,2 --from-code=UTF-8 -o po/keys.pot -f files.txt
    
    $CYGWIN_HOME/bin/sed.exe -i 's/CHARSET/UTF-8/g' po/keys.pot
    
    if [ ! -f po/pl.po ]; then
         $CYGWIN_HOME/bin/cp.exe -v template.po po/pl.po
    fi
    
    $GETTEXT_HOME/msgmerge.exe -U po/pl.po po/keys.pot
    
    export JAVAC=`$CYGWIN_HOME/bin/pwd.exe`/javac.sh
    
    $CYGWIN_HOME/bin/rm.exe -rfv tmp
    $CYGWIN_HOME/bin/mkdir.exe -pv tmp
    export TMPDIR=`$CYGWIN_HOME/bin/pwd.exe`/tmp/
    
    $GETTEXT_HOME/msgfmt.exe --verbose --java2 -d tmp -r com.haso.i18n.Messages po/keys.pot
    $GETTEXT_HOME/msgfmt.exe --verbose --java2 -d tmp -r com.haso.i18n.Messages -l pl po/pl.po
    
    $CYGWIN_HOME/bin/rm.exe -rfv ../src/main/java/com/haso/i18n
    $CYGWIN_HOME/bin/mkdir.exe -pv ../src/main/java/com/haso/i18n
    
    $CYGWIN_HOME/bin/find.exe tmp -name "Messages*.java" | $CYGWIN_HOME/bin/xargs.exe -n 1 $CYGWIN_HOME/bin/cp.exe -vt ../src/main/java/com/haso/i18n/
    

    and executed it from my project root directory with command:

    %CYGWIN_HOME%\bin\bash gettext/run_gettext.sh
    

    where javac.sh is:

    #!/bin/bash
    #
    # A wrapper for calling Javac from Cygwin
    # Original Author: Igor Pechtchanski <pechtcha@cs.nyu.edu
    # Modified by Florian Gattung <fgattung@gmail.com> for msgfmt compatibility
    #
    ME="`basename $0`"
    JAVAC_EXEC="/cygdrive/%JAVA_HOME%/bin/javac.exe"
    ARGS=""
    #
    while [ -n "$1" ]; do
       arg="$1"
       shift
       if [ -d $arg ]; then
             arg="`cygpath -p -w "$arg"`"
       fi
       if [ -f $arg ]; then
             arg="`cygpath -p -w "$arg"`"
       fi
       ARGS="$ARGS '$arg'"
    done
    
    eval "set -- $ARGS"
    exec "$JAVAC_EXEC" "$@"
    

    Created *.java files are then compiled by gradle on CI together with project source code.

    File template.po contains:

    msgid ""
    msgstr ""
    "Content-Type: text/plain; charset=UTF-8\n"