Search code examples
javainternationalizationgettextbean-validation

How to mark string message in bean validation annotation for xgettext?


I am using bean validation and gettext for i18n. How can I mark the message string for translation, so it gets extracted with xgettext? For example

@NotNull(message="Please enter a valid string")
String string;

Normall I call i18n.tr, but how to mark a constant?

Kind regards Christian

Edit: At runtime I am using a custom message interpolator for translation.


Solution

  • I am normally not answering my own questions. But for now I came up with following solution:

    I am marking my strings as follows in an additional comment (I know not DRY anymore):

    //_.trans("Please enter a valid string");
    @NotNull(message="Please enter a valid string")
    String string;
    

    I am calling following script in my pom:

    #!/bin/bash
    
    # $1 -> java source directory
    # $2 -> output file
    # $3 -> po directory
    
    echo "Source Directory: $1"
    echo "Keys File: $2"
    echo "PO Directory: $3"
    
    xgettext --from-code utf-8 -L Java --force-po -ktrc:1c,2 -ktrnc:1c,2,3 -ktr -kmarktr -ktrn:1,2 -k -o "$2" $(find "$1" -name "*.java")
    sed "s/\/\/_/_/g" $(find "$1" -name "*.java") | xgettext -F --from-code utf-8 -L Java -ktrans -k -j -o "$2" -
    
    pofiles=$3/*.po
    shopt -s nullglob
    for i in $pofiles
    do
       echo "msgmerge $i"
       msgmerge --backup=numbered -U $i $2
    done
    

    This script first calls xgettext normally and then calls sed to remove the comment slashes and pipes to xgettext. Thus I have all my keys in keys.pot.

    pom.xml - profile:

        <profile>
            <id>translate</id>
            <build>
                <plugins>
                    <plugin>
                        <artifactId>exec-maven-plugin</artifactId>
                        <groupId>org.codehaus.mojo</groupId>
                        <version>1.2.1</version>
                        <executions>
                            <execution>
                                <id>xgettext</id>
                                <phase>generate-resources</phase>
                                <goals>
                                    <goal>exec</goal>
                                </goals>
                                <configuration>
                                    <executable>sh</executable>
                                    <arguments>
                                        <argument>${project.basedir}/extractkeys.sh</argument>
                                        <argument>src/main/java</argument>
                                        <argument>src/main/resources/po/keys.pot</argument>
                                        <argument>src/main/resources/po</argument>
                                    </arguments>
                                    <workingDirectory>${project.basedir}</workingDirectory>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                    <plugin>
                        <groupId>org.xnap.commons</groupId>
                        <artifactId>maven-gettext-plugin</artifactId>
                        <version>1.2.3</version>
                        <configuration>
                            <keysFile>${project.basedir}/src/main/resources/po/keys.pot</keysFile>
                            <outputDirectory>${project.basedir}/src/main/resources</outputDirectory>
                            <outputFormat>properties</outputFormat>
                            <poDirectory>${project.basedir}/src/main/resources/po</poDirectory>
                            <sourceDirectory>${project.build.sourceDirectory}/ch/sympany/tourist</sourceDirectory>
                            <sourceLocale>en</sourceLocale>
                            <targetBundle>${project.groupId}.Messages</targetBundle>
                        </configuration>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>dist</goal>
                                </goals>
                                <phase>generate-resources</phase>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
    

    I know the build is not platform independent anymore but in a separate profile I can live with it. However, it works also on cygwin for the windows guys.

    My messageinterpolator is as follows:

    public class GettextMessageInterpolator implements MessageInterpolator {
    
        private final MessageInterpolator delegate;
    
        public GettextMessageInterpolator() {
            this.delegate = new ResourceBundleMessageInterpolator();
        }
    
        @Override
        public String interpolate(String message, Context context) {
            return this.interpolate(message, context, ClientLocalLocator.get());
        }
    
        @Override
        public String interpolate(String message, Context context, Locale locale) {   
            I18n i18n = ClientLocalLocator.getI18n();
            String retVal = i18n.tr(message);
            if (StringUtils.isNotBlank(retVal))
                return retVal;
            return delegate.interpolate(message, context, locale);
        }
    
    }