| @c This file is part of the GNU gettext manual. |
| @c Copyright (C) 1995-2020 Free Software Foundation, Inc. |
| @c See the file gettext.texi for copying conditions. |
| |
| @node Java |
| @subsection Java |
| @cindex Java |
| |
| @table @asis |
| @item RPMs |
| java, java2 |
| |
| @item Ubuntu packages |
| default-jdk |
| |
| @item File extension |
| @code{java} |
| |
| @item String syntax |
| "abc", """text block""" |
| |
| @item gettext shorthand |
| i18n("abc") |
| |
| @item gettext/ngettext functions |
| @code{GettextResource.gettext}, @code{GettextResource.ngettext}, |
| @code{GettextResource.pgettext}, @code{GettextResource.npgettext} |
| |
| @item textdomain |
| ---, use @code{ResourceBundle.getResource} instead |
| |
| @item bindtextdomain |
| ---, use CLASSPATH instead |
| |
| @item setlocale |
| automatic |
| |
| @item Prerequisite |
| --- |
| |
| @item Use or emulate GNU gettext |
| ---, uses a Java specific message catalog format |
| |
| @item Extractor |
| @code{xgettext -ki18n} |
| |
| @item Formatting with positions |
| @code{MessageFormat.format "@{1,number@} @{0,number@}"} |
| or @code{String.format "%2$d %1$d"} |
| |
| @item Portability |
| fully portable |
| |
| @item po-mode marking |
| --- |
| @end table |
| |
| Before marking strings as internationalizable, uses of the string |
| concatenation operator need to be converted to @code{MessageFormat} |
| applications. For example, @code{"file "+filename+" not found"} becomes |
| @code{MessageFormat.format("file @{0@} not found", new Object[] @{ filename @})}. |
| Only after this is done, can the strings be marked and extracted. |
| |
| GNU gettext uses the native Java internationalization mechanism, namely |
| @code{ResourceBundle}s. There are two formats of @code{ResourceBundle}s: |
| @code{.properties} files and @code{.class} files. The @code{.properties} |
| format is a text file which the translators can directly edit, like PO |
| files, but which doesn't support plural forms. Whereas the @code{.class} |
| format is compiled from @code{.java} source code and can support plural |
| forms (provided it is accessed through an appropriate API, see below). |
| |
| To convert a PO file to a @code{.properties} file, the @code{msgcat} |
| program can be used with the option @code{--properties-output}. To convert |
| a @code{.properties} file back to a PO file, the @code{msgcat} program |
| can be used with the option @code{--properties-input}. All the tools |
| that manipulate PO files can work with @code{.properties} files as well, |
| if given the @code{--properties-input} and/or @code{--properties-output} |
| option. |
| |
| To convert a PO file to a ResourceBundle class, the @code{msgfmt} program |
| can be used with the option @code{--java} or @code{--java2}. To convert a |
| ResourceBundle back to a PO file, the @code{msgunfmt} program can be used |
| with the option @code{--java}. |
| |
| Two different programmatic APIs can be used to access ResourceBundles. |
| Note that both APIs work with all kinds of ResourceBundles, whether |
| GNU gettext generated classes, or other @code{.class} or @code{.properties} |
| files. |
| |
| @enumerate |
| @item |
| The @code{java.util.ResourceBundle} API. |
| |
| In particular, its @code{getString} function returns a string translation. |
| Note that a missing translation yields a @code{MissingResourceException}. |
| |
| This has the advantage of being the standard API. And it does not require |
| any additional libraries, only the @code{msgcat} generated @code{.properties} |
| files or the @code{msgfmt} generated @code{.class} files. But it cannot do |
| plural handling, even if the resource was generated by @code{msgfmt} from |
| a PO file with plural handling. |
| |
| @item |
| The @code{gnu.gettext.GettextResource} API. |
| |
| Reference documentation in Javadoc 1.1 style format is in the |
| @uref{javadoc2/index.html,javadoc2 directory}. |
| |
| Its @code{gettext} function returns a string translation. Note that when |
| a translation is missing, the @var{msgid} argument is returned unchanged. |
| |
| This has the advantage of having the @code{ngettext} function for plural |
| handling and the @code{pgettext} and @code{npgettext} for strings constraint |
| to a particular context. |
| |
| @cindex @code{libintl} for Java |
| To use this API, one needs the @code{libintl.jar} file which is part of |
| the GNU gettext package and distributed under the LGPL. |
| @end enumerate |
| |
| Four examples, using the second API, are available in the @file{examples} |
| directory: @code{hello-java}, @code{hello-java-awt}, @code{hello-java-swing}, |
| @code{hello-java-qtjambi}. |
| |
| Now, to make use of the API and define a shorthand for @samp{getString}, |
| there are three idioms that you can choose from: |
| |
| @itemize @bullet |
| @item |
| (This one assumes Java 1.5 or newer.) |
| In a unique class of your project, say @samp{Util}, define a static variable |
| holding the @code{ResourceBundle} instance and the shorthand: |
| |
| @smallexample |
| private static ResourceBundle myResources = |
| ResourceBundle.getBundle("domain-name"); |
| public static String i18n(String s) @{ |
| return myResources.getString(s); |
| @} |
| @end smallexample |
| |
| All classes containing internationalized strings then contain |
| |
| @smallexample |
| import static Util.i18n; |
| @end smallexample |
| |
| @noindent |
| and the shorthand is used like this: |
| |
| @smallexample |
| System.out.println(i18n("Operation completed.")); |
| @end smallexample |
| |
| @item |
| In a unique class of your project, say @samp{Util}, define a static variable |
| holding the @code{ResourceBundle} instance: |
| |
| @smallexample |
| public static ResourceBundle myResources = |
| ResourceBundle.getBundle("domain-name"); |
| @end smallexample |
| |
| All classes containing internationalized strings then contain |
| |
| @smallexample |
| private static ResourceBundle res = Util.myResources; |
| private static String i18n(String s) @{ return res.getString(s); @} |
| @end smallexample |
| |
| @noindent |
| and the shorthand is used like this: |
| |
| @smallexample |
| System.out.println(i18n("Operation completed.")); |
| @end smallexample |
| |
| @item |
| You add a class with a very short name, say @samp{S}, containing just the |
| definition of the resource bundle and of the shorthand: |
| |
| @smallexample |
| public class S @{ |
| public static ResourceBundle myResources = |
| ResourceBundle.getBundle("domain-name"); |
| public static String i18n(String s) @{ |
| return myResources.getString(s); |
| @} |
| @} |
| @end smallexample |
| |
| @noindent |
| and the shorthand is used like this: |
| |
| @smallexample |
| System.out.println(S.i18n("Operation completed.")); |
| @end smallexample |
| @end itemize |
| |
| Which of the three idioms you choose, will depend on whether your project |
| requires portability to Java versions prior to Java 1.5 and, if so, whether |
| copying two lines of codes into every class is more acceptable in your project |
| than a class with a single-letter name. |