From: Bruno Haible Date: Tue, 28 Jan 2025 15:47:10 +0000 (+0100) Subject: examples: Add hello-rust example. X-Git-Tag: v0.24~39 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e10853e06cb199aed490837f179ed264f46b05cb;p=thirdparty%2Fgettext.git examples: Add hello-rust example. * gettext-tools/examples/hello-rust/INSTALL: New file. * gettext-tools/examples/hello-rust/autogen.sh: New file. * gettext-tools/examples/hello-rust/autoclean.sh: New file. * gettext-tools/examples/hello-rust/Cargo.toml.in: New file. * gettext-tools/examples/hello-rust/src/main.rs.in: New file. * gettext-tools/examples/hello-rust/Makefile.am: New file. * gettext-tools/examples/hello-rust/configure.ac: New file. * gettext-tools/examples/hello-rust/m4/Makefile.am: New file. * gettext-tools/examples/hello-rust/po/Makefile.am: New file. * gettext-tools/examples/hello-rust/po/LINGUAS: New file. * gettext-tools/examples/Makefile.am (EXAMPLESFILES, EXAMPLESDIRS): Add hello-rust. * gettext-tools/examples/po/Makefile.am (POTFILES, SMALLPOTS): Update for hello-rust. (hello-rust.pot): New target. (SMALLPOFILES_FOR_lang): Update for hello-rust. ($(srcdir)/../hello-rust/po/$(LL).po): New rule. * gettext-tools/examples/check-examples (func_check_autoclean_all, func_check_distclean_all, func_check_maintainerclean_all, func_check_maintainerclean_vpath_all, func_check_dist_all, func_check_dist_vpath_all, func_check_install_all, func_check_uninstall_all, func_check_distcheck_all, func_check_all): Handle hello-rust as well. (func_check): Add a more useful body. * gettext-tools/examples/README: Mention hello-rust. * NEWS: Likewise. --- diff --git a/NEWS b/NEWS index 8da488fb5..507da43b1 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,7 @@ Version 0.24 - January 2025 - xgettext now supports Rust. - 'msgfmt -c' now verifies the syntax of translations of Rust format strings. + - A new example 'hello-rust' has been added. * C++: - A new example 'hello-c++-gnome3' has been added. * Ruby: diff --git a/gettext-tools/examples/Makefile.am b/gettext-tools/examples/Makefile.am index f5eb42e15..0774ddc42 100644 --- a/gettext-tools/examples/Makefile.am +++ b/gettext-tools/examples/Makefile.am @@ -1,5 +1,5 @@ ## Makefile for the gettext-tools/examples subdirectory of GNU gettext -## Copyright (C) 2001-2024 Free Software Foundation, Inc. +## Copyright (C) 2001-2025 Free Software Foundation, Inc. ## ## This program is free software: you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -333,6 +333,16 @@ EXAMPLESFILES = \ hello-csharp-forms/m4/Makefile.am \ hello-csharp-forms/po/Makefile.am \ \ + hello-rust/INSTALL \ + hello-rust/autogen.sh \ + hello-rust/autoclean.sh \ + hello-rust/Cargo.toml.in \ + hello-rust/src/main.rs.in \ + hello-rust/Makefile.am \ + hello-rust/configure.ac \ + hello-rust/m4/Makefile.am \ + hello-rust/po/Makefile.am \ + \ hello-ruby/INSTALL \ hello-ruby/autogen.sh \ hello-ruby/autoclean.sh \ @@ -436,6 +446,7 @@ EXAMPLESDIRS = \ hello-java-qtjambi \ hello-csharp \ hello-csharp-forms \ + hello-rust \ hello-ruby \ hello-gawk \ hello-pascal \ diff --git a/gettext-tools/examples/README b/gettext-tools/examples/README index ec14a2842..9545209ce 100644 --- a/gettext-tools/examples/README +++ b/gettext-tools/examples/README @@ -30,6 +30,7 @@ environment. hello-java-qtjambi Java Qt hello-csharp C# hello-csharp-forms C# Forms + hello-rust Rust hello-ruby Ruby hello-gawk awk hello-pascal Pascal @@ -73,6 +74,7 @@ Makefile types: hello-librep .gmo Makefile.am hello-guile .gmo Makefile.am hello-smalltalk .gmo Makefile.am + hello-rust .gmo Makefile.am hello-ruby .gmo Makefile.am hello-gawk .gmo Makefile.am hello-pascal .gmo Makefile.am diff --git a/gettext-tools/examples/check-examples b/gettext-tools/examples/check-examples index 36551167f..7bf013c8f 100755 --- a/gettext-tools/examples/check-examples +++ b/gettext-tools/examples/check-examples @@ -1,7 +1,7 @@ #!/bin/bash # Script that checks against build infrastructure mistakes in the examples. -# Copyright (C) 2018-2024 Free Software Foundation, Inc. +# Copyright (C) 2018-2025 Free Software Foundation, Inc. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -153,6 +153,7 @@ func_check_autoclean_all () func_check_autoclean hello-java-qtjambi func_check_autoclean hello-csharp func_check_autoclean hello-csharp-forms + func_check_autoclean hello-rust func_check_autoclean hello-ruby func_check_autoclean hello-gawk func_check_autoclean hello-pascal @@ -227,6 +228,7 @@ func_check_distclean_all () func_check_distclean hello-java-qtjambi func_check_distclean hello-csharp func_check_distclean hello-csharp-forms + func_check_distclean hello-rust func_check_distclean hello-ruby func_check_distclean hello-gawk func_check_distclean hello-pascal @@ -303,6 +305,7 @@ func_check_maintainerclean_all () #func_check_maintainerclean hello-java-qtjambi func_check_maintainerclean hello-csharp func_check_maintainerclean hello-csharp-forms + func_check_maintainerclean hello-rust func_check_maintainerclean hello-ruby func_check_maintainerclean hello-gawk func_check_maintainerclean hello-pascal @@ -382,6 +385,7 @@ func_check_maintainerclean_vpath_all () #func_check_maintainerclean_vpath hello-java-qtjambi func_check_maintainerclean_vpath hello-csharp func_check_maintainerclean_vpath hello-csharp-forms + func_check_maintainerclean_vpath hello-rust func_check_maintainerclean_vpath hello-ruby func_check_maintainerclean_vpath hello-gawk func_check_maintainerclean_vpath hello-pascal @@ -468,6 +472,7 @@ func_check_dist_all () #func_check_dist hello-java-qtjambi func_check_dist hello-csharp func_check_dist hello-csharp-forms + func_check_dist hello-rust func_check_dist hello-ruby func_check_dist hello-gawk func_check_dist hello-pascal @@ -554,6 +559,7 @@ func_check_dist_vpath_all () #func_check_dist_vpath hello-java-qtjambi func_check_dist_vpath hello-csharp func_check_dist_vpath hello-csharp-forms + func_check_dist_vpath hello-rust func_check_dist_vpath hello-ruby func_check_dist_vpath hello-gawk func_check_dist_vpath hello-pascal @@ -632,6 +638,7 @@ func_check_install_all () #func_check_install hello-java-qtjambi func_check_install hello-csharp func_check_install hello-csharp-forms + func_check_install hello-rust func_check_install hello-ruby func_check_install hello-gawk func_check_install hello-pascal @@ -707,6 +714,7 @@ func_check_uninstall_all () #func_check_uninstall hello-java-qtjambi func_check_uninstall hello-csharp func_check_uninstall hello-csharp-forms + func_check_uninstall hello-rust func_check_uninstall hello-ruby func_check_uninstall hello-gawk func_check_uninstall hello-pascal @@ -784,6 +792,7 @@ func_check_distcheck_all () #func_check_distcheck hello-java-qtjambi func_check_distcheck hello-csharp func_check_distcheck hello-csharp-forms + func_check_distcheck hello-rust func_check_distcheck hello-ruby func_check_distcheck hello-gawk func_check_distcheck hello-pascal @@ -802,10 +811,18 @@ func_check_distcheck_all () # If you want to extend this script: -# A dummy check function. +# A check function for a single sample. func_check () { - : + func_check_autoclean "$1" + func_check_distclean "$1" + func_check_maintainerclean "$1" + func_check_maintainerclean_vpath "$1" + func_check_dist "$1" + func_check_dist_vpath "$1" + func_check_install "$1" + func_check_uninstall "$1" + func_check_distcheck "$1" } # Complete list of samples. @@ -836,6 +853,7 @@ func_check_all () func_check hello-java-qtjambi func_check hello-csharp func_check hello-csharp-forms + func_check hello-rust func_check hello-ruby func_check hello-gawk func_check hello-pascal diff --git a/gettext-tools/examples/hello-rust/Cargo.toml.in b/gettext-tools/examples/hello-rust/Cargo.toml.in new file mode 100644 index 000000000..9938ff241 --- /dev/null +++ b/gettext-tools/examples/hello-rust/Cargo.toml.in @@ -0,0 +1,8 @@ +[package] +name = "hello" +version = "0.0.0" +edition = "2021" + +[dependencies] +gettext-rs = "0.7.2" +formatx = "0.2.3" diff --git a/gettext-tools/examples/hello-rust/INSTALL b/gettext-tools/examples/hello-rust/INSTALL new file mode 100644 index 000000000..6e23c6209 --- /dev/null +++ b/gettext-tools/examples/hello-rust/INSTALL @@ -0,0 +1,13 @@ +This example relies on Rust (programs: rustc, cargo) +and the following crates: + - gettext-rs (not 'gettext', not 'xtr'), + - formatx (not 'strfmt'). + +Installation: + ./autogen.sh + ./configure --prefix=/some/prefix + make + make install +Cleanup: + make distclean + ./autoclean.sh diff --git a/gettext-tools/examples/hello-rust/Makefile.am b/gettext-tools/examples/hello-rust/Makefile.am new file mode 100644 index 000000000..0502c3950 --- /dev/null +++ b/gettext-tools/examples/hello-rust/Makefile.am @@ -0,0 +1,62 @@ +# Example for use of GNU gettext. +# This file is in the public domain. +# +# Makefile configuration - processed by automake. + +# General automake options. +AUTOMAKE_OPTIONS = foreign +ACLOCAL_AMFLAGS = -I m4 + +# The list of subdirectories containing Makefiles. +SUBDIRS = m4 po + +# The list of programs that are built. +bin_RUSTPROGRAMS = hello + +# The source files of the 'hello' program. +hello_SOURCES = src/main.rs + +DISTCLEANFILES = + +# Additional files to be distributed. +EXTRA_DIST = autogen.sh autoclean.sh + + +# ----------------- General rules for compiling Rust programs ----------------- + +# Support for VPATH builds. +DISTCLEANFILES += Cargo.toml +EXTRA_DIST += Cargo.toml.in + +DISTCLEANFILES += Cargo.lock + + +# Rules for compiling Rust programs. + +all-local: Cargo.toml $(hello_SOURCES) + $(CARGO) build + +check-local: + $(CARGO) test + +# The target/ directory takes 2.5 to 5 minutes to rebuild. Therefore +# we delete it only at "make maintainer-clean", not at "make distclean". +maintainer-clean-local: +# $(CARGO) clean + rm -rf target +# Customize "make distcheck" accordingly. +distcleancheck_listfiles = \ + find . \( -type f \ + -a \! \( -name .nfs* -o -name .smb* -o -name .__afs* \) \ + -a '!' -path './target/*' \) \ + -print + +install-exec-local: all-local + $(MKDIR_P) $(DESTDIR)$(bindir) + $(INSTALL_PROGRAM) target/debug/hello$(EXEEXT) $(DESTDIR)$(bindir)/hello + +installdirs-local: + $(MKDIR_P) $(DESTDIR)$(bindir) + +uninstall-local: + rm -f $(DESTDIR)$(bindir)/hello diff --git a/gettext-tools/examples/hello-rust/autoclean.sh b/gettext-tools/examples/hello-rust/autoclean.sh new file mode 100755 index 000000000..c17d7ef9d --- /dev/null +++ b/gettext-tools/examples/hello-rust/autoclean.sh @@ -0,0 +1,32 @@ +#!/bin/sh +# Example for use of GNU gettext. +# This file is in the public domain. +# +# Script for cleaning all autogenerated files. + +test ! -f Makefile || make distclean +# Do the equivalent of "make maintainer-clean", even without the Makefile. +rm -rf target +rm -rf autom4te.cache + +# Brought in by explicit copy. +rm -f m4/nls.m4 +rm -f m4/po.m4 +rm -f m4/progtest.m4 +rm -f po/remove-potcdate.sed + +# Generated by aclocal. +rm -f aclocal.m4 + +# Generated by autoconf. +rm -f configure + +# Generated or brought in by automake. +rm -f Makefile.in +rm -f m4/Makefile.in +rm -f po/Makefile.in +rm -f install-sh +rm -f missing +rm -f po/*.pot +rm -f po/stamp-po +rm -f po/*.gmo diff --git a/gettext-tools/examples/hello-rust/autogen.sh b/gettext-tools/examples/hello-rust/autogen.sh new file mode 100755 index 000000000..a972da804 --- /dev/null +++ b/gettext-tools/examples/hello-rust/autogen.sh @@ -0,0 +1,44 @@ +#!/bin/sh +# Example for use of GNU gettext. +# This file is in the public domain. +# +# Script for regenerating all autogenerated files. + +if test -r ../Makefile.am; then + # Inside the gettext source directory. + GETTEXT_TOPSRCDIR=../../.. +else + if test -r ../Makefile; then + # Inside a gettext build directory. + GETTEXT_TOOLS_SRCDIR=`sed -n -e 's,^top_srcdir *= *\(.*\)$,\1,p' ../Makefile` + # Adjust a relative top_srcdir. + case $GETTEXT_TOOLS_SRCDIR in + /*) ;; + *) GETTEXT_TOOLS_SRCDIR=../$GETTEXT_TOOLS_SRCDIR ;; + esac + GETTEXT_TOPSRCDIR=$GETTEXT_TOOLS_SRCDIR/../.. + else + # Installed under ${prefix}/share/doc/gettext/examples. + . ../installpaths + fi +fi + +cp -p ${ACLOCALDIR-$GETTEXT_TOPSRCDIR/gettext-runtime/m4}/nls.m4 m4/nls.m4 +cp -p ${ACLOCALDIR-$GETTEXT_TOPSRCDIR/gettext-runtime/m4}/po.m4 m4/po.m4 +cp -p ${ACLOCALDIR-$GETTEXT_TOPSRCDIR/gettext-runtime/m4}/progtest.m4 m4/progtest.m4 +cp -p ${GETTEXTSRCPODIR-$GETTEXT_TOPSRCDIR/gettext-runtime/po}/remove-potcdate.sed po/remove-potcdate.sed + +aclocal -I m4 + +autoconf + +automake -a -c + +cd po +for f in *.po; do + if test -r "$f"; then + lang=`echo $f | sed -e 's,\.po$,,'` + msgfmt -c -o $lang.gmo $lang.po + fi +done +cd .. diff --git a/gettext-tools/examples/hello-rust/configure.ac b/gettext-tools/examples/hello-rust/configure.ac new file mode 100644 index 000000000..67cf39d4d --- /dev/null +++ b/gettext-tools/examples/hello-rust/configure.ac @@ -0,0 +1,44 @@ +dnl Example for use of GNU gettext. +dnl This file is in the public domain. +dnl +dnl Configuration file - processed by autoconf. + +AC_INIT([hello-rust], [0]) +AC_CONFIG_SRCDIR([src/main.rs.in]) +AM_INIT_AUTOMAKE([1.11]) + +dnl Check for availability of the Cargo program. +AC_PATH_PROG([CARGO], [cargo]) +if test -z "$CARGO"; then + echo "*** Essential program 'cargo' not found" 1>&2 + exit 1 +fi +AC_SUBST([CARGO]) + +dnl The installed program must know where to find its message catalogs. +dnl Unfortunately, prefix gets only finally determined at the end of configure. +if test "X$prefix" = "XNONE"; then + final_prefix="$ac_default_prefix" +else + final_prefix="$prefix" +fi +save_prefix="$prefix" +prefix="$final_prefix" +eval "datarootdir=\"${datarootdir}\"" +eval "localedir=\"${datarootdir}/locale\"" +prefix="$save_prefix" +AC_SUBST([localedir]) + +dnl Support for the po directory. +AM_PO_SUBDIRS + +AC_CONFIG_FILES([Makefile src/main.rs]) +dnl Support for VPATH builds: +dnl We need a copy of Cargo.toml in the build directory, because +dnl - Cargo.lock needs to reside in the build directory and +dnl - src/main.rs is in the build directory as well. +dnl Cf. . +AC_CONFIG_FILES([Cargo.toml]) +AC_CONFIG_FILES([m4/Makefile]) +AC_CONFIG_FILES([po/Makefile], [AM_POSTPROCESS_PO_MAKEFILE]) +AC_OUTPUT diff --git a/gettext-tools/examples/hello-rust/m4/Makefile.am b/gettext-tools/examples/hello-rust/m4/Makefile.am new file mode 100644 index 000000000..8a841b31f --- /dev/null +++ b/gettext-tools/examples/hello-rust/m4/Makefile.am @@ -0,0 +1,2 @@ +EXTRA_DIST = \ + nls.m4 po.m4 diff --git a/gettext-tools/examples/hello-rust/po/LINGUAS b/gettext-tools/examples/hello-rust/po/LINGUAS new file mode 100644 index 000000000..dc4a82afb --- /dev/null +++ b/gettext-tools/examples/hello-rust/po/LINGUAS @@ -0,0 +1,5 @@ +# Example for use of GNU gettext. +# This file is in the public domain. +# +# Set of available languages. +af ast bg ca cs da de el eo es fi fr ga gl hr hu id it ja ka ky lv ms mt nb nl nn pl pt pt_BR ro ru sk sl sq sr sv ta tr uk vi zh_CN zh_HK zh_TW diff --git a/gettext-tools/examples/hello-rust/po/Makefile.am b/gettext-tools/examples/hello-rust/po/Makefile.am new file mode 100644 index 000000000..4a6a86834 --- /dev/null +++ b/gettext-tools/examples/hello-rust/po/Makefile.am @@ -0,0 +1,434 @@ +# Example for use of GNU gettext. +# This file is in the public domain. +# +# Makefile configuration - processed by automake. + +# List of files which contain translatable strings. +POTFILES = \ + src/main.rs.in + +# Usually the message domain is the same as the package name. +DOMAIN = $(PACKAGE) + +# These options get passed to xgettext. +XGETTEXT_OPTIONS = + +# This is the copyright holder that gets inserted into the header of the +# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding +# package. (Note that the msgstr strings, extracted from the package's +# sources, belong to the copyright holder of the package.) Translators are +# expected to transfer the copyright for their translations to this person +# or entity, or to disclaim their copyright. The empty string stands for +# the public domain; in this case the translators are expected to disclaim +# their copyright. +COPYRIGHT_HOLDER = Yoyodyne, Inc. + +# This tells whether or not to prepend "GNU " prefix to the package +# name that gets inserted into the header of the $(DOMAIN).pot file. +# Possible values are "yes", "no", or empty. If it is empty, try to +# detect it automatically by scanning the files in $(top_srcdir) for +# "GNU packagename" string. +PACKAGE_GNU = no + +# This is the email address or URL to which the translators shall report +# bugs in the untranslated strings: +# - Strings which are not entire sentences, see the maintainer guidelines +# in the GNU gettext documentation, section 'Preparing Strings'. +# - Strings which use unclear terms or require additional context to be +# understood. +# - Strings which make invalid assumptions about notation of date, time or +# money. +# - Pluralisation problems. +# - Incorrect English spelling. +# - Incorrect formatting. +# It can be your email address, or a mailing list address where translators +# can write to without being subscribed, or the URL of a web page through +# which the translators can contact you. +MSGID_BUGS_ADDRESS = bug-gettext@gnu.org + +# This is the list of locale categories, beyond LC_MESSAGES, for which the +# message catalogs shall be used. It is usually empty. +EXTRA_LOCALE_CATEGORIES = + +# These options get passed to msgmerge. +# Useful options are in particular: +# --previous to keep previous msgids of translated messages +MSGMERGE_OPTIONS = + +# These options get passed to msginit. +# If you want to disable line wrapping when writing PO files, add +# --no-wrap to MSGMERGE_OPTIONS, XGETTEXT_OPTIONS, and +# MSGINIT_OPTIONS. +MSGINIT_OPTIONS = + +MSGMERGE = @MSGMERGE@ +MSGMERGE_UPDATE = @MSGMERGE@ --update +MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@ +MSGINIT = msginit +MSGCONV = msgconv +MSGFILTER = msgfilter + +# This is computed as $(foreach file, $(POTFILES), $(top_srcdir)/$(file)) +POTFILES_DEPS != for file in $(POTFILES); do echo $(top_srcdir)/$$file; done + +# The set of available translations. +ALL_LINGUAS != if test -f $(srcdir)/LINGUAS; then \ + sed -e '/^\#/d' < $(srcdir)/LINGUAS; \ + else \ + echo $(LINGUAS); \ + fi +# This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) +POFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.po; done +# This is computed as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) +GMOFILES != for lang in $(ALL_LINGUAS); do echo $(srcdir)/$$lang.gmo; done +# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) +UPDATEPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.po-update; done +# This is computed as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) +DUMMYPOFILES != for lang in $(ALL_LINGUAS); do echo $$lang.nop; done + +# The set of desired translations, as specified by the installer or distributor. +DESIRED_LINGUAS = @DESIRED_LINGUAS@ +# The set of translations to install. This is computed based on $(ALL_LINGUAS) +# and $(DESIRED_LINGUAS). It is a subset of $(ALL_LINGUAS). +# We use the presentlang catalog if desiredlang is +# a. equal to presentlang, or +# b. a variant of presentlang (because in this case, presentlang can be used +# as a fallback for messages which are not translated in the desiredlang +# catalog). +INST_LINGUAS != for presentlang in $(ALL_LINGUAS); do \ + useit=false; \ + for desiredlang in $(DESIRED_LINGUAS); do \ + case "$$desiredlang" in \ + "$$presentlang" | "$$presentlang"_* | "$$presentlang".* | "$$presentlang"@*) \ + useit=true ;; \ + esac; \ + done; \ + if $$useit; then echo $$presentlang; fi; \ + done +# This is computed as $(foreach lang, $(INST_LINGUAS), $(lang).gmo) +CATALOGS != for lang in $(INST_LINGUAS); do echo $$lang.gmo; done + +SUFFIXES = .po .gmo .nop .po-create .po-update + +# The .pot file, stamp-po, .po files, and .gmo files appear in release tarballs. +# The GNU Coding Standards say in +# : +# "GNU distributions usually contain some files which are not source files +# ... . Since these files normally appear in the source directory, they +# should always appear in the source directory, not in the build directory. +# So Makefile rules to update them should put the updated files in the +# source directory." +# Therefore we put these files in the source directory, not the build directory. + +# During .po -> .gmo conversion, take into account the most recent changes to +# the .pot file. This eliminates the need to update the .po files when the +# .pot file has changed, which would be troublesome if the .po files are put +# under version control. +$(GMOFILES): $(srcdir)/$(DOMAIN).pot +.po.gmo: + @lang=`echo $* | sed -e 's,.*/,,'`; \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}rm -f $${lang}.gmo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) -o $${lang}.1po $${lang}.po $(DOMAIN).pot && $(GMSGFMT) -c --statistics --verbose -o $${lang}.gmo $${lang}.1po && rm -f $${lang}.1po"; \ + cd $(srcdir) && \ + rm -f $${lang}.gmo && \ + $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) -o $${lang}.1po $${lang}.po $(DOMAIN).pot && \ + $(GMSGFMT) -c --statistics --verbose -o t-$${lang}.gmo $${lang}.1po && \ + mv t-$${lang}.gmo $${lang}.gmo && \ + rm -f $${lang}.1po + + +all-local: all-local-@USE_NLS@ + +all-local-yes: $(srcdir)/stamp-po +all-local-no: + +# $(srcdir)/$(DOMAIN).pot is only created when needed. When xgettext finds no +# internationalized messages, no $(srcdir)/$(DOMAIN).pot is created (because +# we don't want to bother translators with empty POT files). We assume that +# LINGUAS is empty in this case, i.e. $(POFILES) and $(GMOFILES) are empty. +# In this case, $(srcdir)/stamp-po is a nop (i.e. a phony target). + +# $(srcdir)/stamp-po is a timestamp denoting the last time at which the CATALOGS +# have been loosely updated. Its purpose is that when a developer or translator +# checks out the package from a version control system, and the $(DOMAIN).pot +# file is not under version control, "make" will update the $(DOMAIN).pot and +# the $(CATALOGS), but subsequent invocations of "make" will do nothing. This +# timestamp would not be necessary if updating the $(CATALOGS) would always +# touch them; however, the rule for $(POFILES) has been designed to not touch +# files that don't need to be changed. +$(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot + test ! -f $(srcdir)/$(DOMAIN).pot || \ + test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES) + @test ! -f $(srcdir)/$(DOMAIN).pot || { \ + echo "touch $(srcdir)/stamp-po" && \ + echo timestamp > $(srcdir)/stamp-poT && \ + mv $(srcdir)/stamp-poT $(srcdir)/stamp-po; \ + } + +# This target rebuilds $(DOMAIN).pot; it is an expensive operation. +# Note that $(DOMAIN).pot is not touched if it doesn't need to be changed. +# The determination of whether the package xyz is a GNU one is based on the +# heuristic whether some file in the top level directory mentions "GNU xyz". +# If GNU 'find' is available, we avoid grepping through monster files. +$(DOMAIN).pot-update: $(POTFILES_DEPS) + package_gnu="$(PACKAGE_GNU)"; \ + test -n "$$package_gnu" || { \ + if { if (LC_ALL=C find --version) 2>/dev/null | grep GNU >/dev/null; then \ + LC_ALL=C find -L $(top_srcdir) -maxdepth 1 -type f -size -10000000c -exec grep -i 'GNU $(PACKAGE)' /dev/null '{}' ';' 2>/dev/null; \ + else \ + LC_ALL=C grep -i 'GNU $(PACKAGE)' $(top_srcdir)/* 2>/dev/null; \ + fi; \ + } | grep -v 'libtool:' >/dev/null; then \ + package_gnu=yes; \ + else \ + package_gnu=no; \ + fi; \ + }; \ + if test "$$package_gnu" = "yes"; then \ + package_prefix='GNU '; \ + else \ + package_prefix=''; \ + fi; \ + if test -n '$(MSGID_BUGS_ADDRESS)'; then \ + msgid_bugs_address='$(MSGID_BUGS_ADDRESS)'; \ + else \ + msgid_bugs_address='$(PACKAGE_BUGREPORT)'; \ + fi; \ + case `$(XGETTEXT) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].* | 0.16 | 0.16.[0-1]*) \ + $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ + --add-comments=TRANSLATORS: \ + --copyright-holder='$(COPYRIGHT_HOLDER)' \ + --msgid-bugs-address="$$msgid_bugs_address" \ + $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ + $(POTFILES) \ + ;; \ + *) \ + $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ + --add-comments=TRANSLATORS: \ + --copyright-holder='$(COPYRIGHT_HOLDER)' \ + --package-name="$${package_prefix}$(PACKAGE)" \ + --package-version='$(VERSION)' \ + --msgid-bugs-address="$$msgid_bugs_address" \ + $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ + $(POTFILES) \ + ;; \ + esac + test ! -f $(DOMAIN).po || { \ + if test -f $(srcdir)/$(DOMAIN).pot-header; then \ + sed -e '1,/^#$$/d' < $(DOMAIN).po > $(DOMAIN).1po && \ + cat $(srcdir)/$(DOMAIN).pot-header $(DOMAIN).1po > $(DOMAIN).po && \ + rm -f $(DOMAIN).1po \ + || exit 1; \ + fi; \ + if test -f $(srcdir)/$(DOMAIN).pot; then \ + sed -f $(srcdir)/remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \ + sed -f $(srcdir)/remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \ + if cmp $(DOMAIN).1po $(DOMAIN).2po >/dev/null 2>&1; then \ + rm -f $(DOMAIN).1po $(DOMAIN).2po $(DOMAIN).po; \ + else \ + rm -f $(DOMAIN).1po $(DOMAIN).2po $(srcdir)/$(DOMAIN).pot && \ + mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ + fi; \ + else \ + mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ + fi; \ + } + +# This rule has no dependencies: we don't need to update $(DOMAIN).pot at +# every "make" invocation, only create it when it is missing. +# Only "make $(DOMAIN).pot-update" or "make dist" will force an update. +$(srcdir)/$(DOMAIN).pot: + $(MAKE) $(DOMAIN).pot-update + +# This target rebuilds a PO file if $(DOMAIN).pot has changed. +# Note that a PO file is not touched if it doesn't need to be changed. +$(POFILES): $(srcdir)/$(DOMAIN).pot + @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \ + if test -f "$(srcdir)/$${lang}.po"; then \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}$(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \ + cd $(srcdir) \ + && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \ + $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \ + 0.1[1-5] | 0.1[1-5].*) \ + $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \ + 0.1[6-7] | 0.1[6-7].*) \ + $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \ + *) \ + $(MSGMERGE_UPDATE) --quiet $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \ + esac; \ + }; \ + else \ + $(MAKE) $${lang}.po-create; \ + fi + + +install-data-local: install-data-local-@USE_NLS@ +install-data-local-no: all-local +install-data-local-yes: all-local + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + dir=$(localedir)/$$lang/LC_MESSAGES; \ + $(MKDIR_P) $(DESTDIR)$$dir; \ + if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \ + $(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \ + echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \ + for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ + if test -n "$$lc"; then \ + if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ + link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ + mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ + for file in *; do \ + if test -f $$file; then \ + ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ + fi; \ + done); \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + else \ + if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ + :; \ + else \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + fi; \ + fi; \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ + ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ + cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \ + fi; \ + done; \ + done + +installdirs-local: installdirs-local-@USE_NLS@ +installdirs-local-no: +installdirs-local-yes: + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + dir=$(localedir)/$$lang/LC_MESSAGES; \ + $(MKDIR_P) $(DESTDIR)$$dir; \ + for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ + if test -n "$$lc"; then \ + if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ + link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ + mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ + for file in *; do \ + if test -f $$file; then \ + ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ + fi; \ + done); \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + else \ + if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ + :; \ + else \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + fi; \ + fi; \ + fi; \ + done; \ + done + +uninstall-local: uninstall-local-@USE_NLS@ +uninstall-local-no: +uninstall-local-yes: + catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + done; \ + done + +html ID: + +MOSTLYCLEANFILES = +MOSTLYCLEANFILES += stamp-poT +MOSTLYCLEANFILES += core core.* *.stackdump $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po +MOSTLYCLEANFILES += *.o + +MAINTAINERCLEANFILES = $(DOMAIN).pot stamp-po $(GMOFILES) + +EXTRA_DIST = remove-potcdate.sed LINGUAS $(POFILES) $(GMOFILES) + +# Hidden from automake, but really activated. Works around an automake-1.5 bug. +#distdir: distdir1 +distdir1: + $(MAKE) update-po + $(MAKE) $(srcdir)/stamp-po + @if test -f $(srcdir)/$(DOMAIN).pot; then \ + for file in $(DOMAIN).pot stamp-po; do \ + if test -f $$file; then d=.; else d=$(srcdir); fi; \ + cp -p $$d/$$file $(distdir)/$$file || exit 1; \ + done; \ + else \ + case $(XGETTEXT) in \ + :) echo "Warning: Creating a tarball without '$(DOMAIN).pot', because a suitable 'xgettext' program was not found in PATH." 1>&2;; \ + *) echo "Warning: Creating a tarball without '$(DOMAIN).pot', because 'xgettext' found no strings to extract. Check the POTFILES and the XGETTEXT_OPTIONS in the Makefile.am file." 1>&2;; \ + esac; \ + fi + +update-po: Makefile + $(MAKE) $(DOMAIN).pot-update + test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES) + $(MAKE) update-gmo + +# General rule for creating PO files. + +.nop.po-create: + @lang=`echo $@ | sed -e 's/\.po-create$$//'`; \ + echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \ + exit 1 + +# General rule for updating PO files. + +.nop.po-update: + @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \ + tmpdir=`pwd`; \ + echo "$$lang:"; \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}$(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \ + cd $(srcdir); \ + if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.10 | 0.10.*) \ + $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \ + 0.1[1-5] | 0.1[1-5].*) \ + $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \ + 0.1[6-7] | 0.1[6-7].*) \ + $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \ + *) \ + $(MSGMERGE) --quiet $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \ + esac; \ + }; then \ + if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ + rm -f $$tmpdir/$$lang.new.po; \ + else \ + if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ + :; \ + else \ + echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ + exit 1; \ + fi; \ + fi; \ + else \ + echo "msgmerge for $$lang.po failed!" 1>&2; \ + rm -f $$tmpdir/$$lang.new.po; \ + fi + +$(DUMMYPOFILES): + +update-gmo: Makefile $(GMOFILES) + @: diff --git a/gettext-tools/examples/hello-rust/src/main.rs.in b/gettext-tools/examples/hello-rust/src/main.rs.in new file mode 100644 index 000000000..a12464f7c --- /dev/null +++ b/gettext-tools/examples/hello-rust/src/main.rs.in @@ -0,0 +1,32 @@ +/* Example for use of GNU gettext. + This file is in the public domain. + + Source code of the Rust program. */ + +/* gettext-rs + Home: https://crates.io/crates/gettext-rs + https://lib.rs/crates/gettext-rs + https://github.com/gettext-rs/gettext-rs + Documentation: https://docs.rs/gettext-rs/latest/gettextrs/ */ +use gettextrs::*; + +/* formatx + Home: https://crates.io/crates/formatx + https://lib.rs/crates/formatx + https://github.com/clitic/formatx + Documentation: https://docs.rs/formatx/latest/formatx/ */ +use formatx::*; + +use std::process; + +fn main() { + setlocale (LocaleCategory::LcAll, ""); + + textdomain ("hello-rust").expect ("textdomain failed"); + bindtextdomain ("hello-rust", "@localedir@").expect ("bindtextdomain failed"); + /* gettext-rs requires UTF-8 encoding. */ + bind_textdomain_codeset ("hello-rust", "UTF-8").expect ("bind_textdomain_codeset failed"); + + println! ("{}", gettext ("Hello, world!")); + println! ("{}", formatx! (gettext ("This program is running as process number {}."), process::id ()).unwrap ()); +} diff --git a/gettext-tools/examples/po/Makefile.am b/gettext-tools/examples/po/Makefile.am index 7ee12466d..532c9c3cb 100644 --- a/gettext-tools/examples/po/Makefile.am +++ b/gettext-tools/examples/po/Makefile.am @@ -1,5 +1,5 @@ ## Makefile for the gettext-tools/examples/po subdirectory of GNU gettext -## Copyright (C) 1995-2024 Free Software Foundation, Inc. +## Copyright (C) 1995-2025 Free Software Foundation, Inc. ## ## This program is free software: you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -59,6 +59,7 @@ POTFILES = \ hello-java-qtjambi/Hello.java \ hello-csharp/hello.cs \ hello-csharp-forms/hello.cs \ + hello-rust/src/main.rs.in \ hello-ruby/hello.rb \ hello-gawk/hello.awk \ hello-pascal/hello.pas \ @@ -96,6 +97,7 @@ SMALLPOTS = \ hello-java-qtjambi.pot \ hello-csharp.pot \ hello-csharp-forms.pot \ + hello-rust.pot \ hello-ruby.pot \ hello-gawk.pot \ hello-pascal.pot \ @@ -323,6 +325,9 @@ hello-csharp.pot : $(POTFILES_DEPS) hello-csharp-forms.pot : $(POTFILES_DEPS) $(USE_BUILT_PROGS) $(SHELL) '$(srcdir)/xsmallpot.sh' '$(srcdir)' hello-csharp-forms +hello-rust.pot : $(POTFILES_DEPS) + $(USE_BUILT_PROGS) $(SHELL) '$(srcdir)/xsmallpot.sh' '$(srcdir)' hello-rust + hello-ruby.pot : $(POTFILES_DEPS) $(USE_BUILT_PROGS) $(SHELL) '$(srcdir)/xsmallpot.sh' '$(srcdir)' hello-ruby @@ -448,6 +453,7 @@ SMALLPOFILES_FOR_lang = \ $(srcdir)/../hello-java-qtjambi/po/$$lang.po \ $(srcdir)/../hello-csharp/po/$$lang.po \ $(srcdir)/../hello-csharp-forms/po/$$lang.po \ + $(srcdir)/../hello-rust/po/$$lang.po \ $(srcdir)/../hello-ruby/po/$$lang.po \ $(srcdir)/../hello-gawk/po/$$lang.po \ $(srcdir)/../hello-pascal/po/$$lang.po \ @@ -532,6 +538,9 @@ $(srcdir)/../hello-csharp/po/$(LL).po: $(srcdir)/hello-csharp.pot $(srcdir)/$(LL $(srcdir)/../hello-csharp-forms/po/$(LL).po: $(srcdir)/hello-csharp-forms.pot $(srcdir)/$(LL).po $(USE_BUILT_PROGS) cd $(srcdir) && $(SHELL) mmsmallpo.sh hello-csharp-forms $(LL) +$(srcdir)/../hello-rust/po/$(LL).po: $(srcdir)/hello-rust.pot $(srcdir)/$(LL).po + $(USE_BUILT_PROGS) cd $(srcdir) && $(SHELL) mmsmallpo.sh hello-rust $(LL) + $(srcdir)/../hello-ruby/po/$(LL).po: $(srcdir)/hello-ruby.pot $(srcdir)/$(LL).po $(USE_BUILT_PROGS) cd $(srcdir) && $(SHELL) mmsmallpo.sh hello-ruby $(LL)