@@ -569,7 +569,9 @@ INSTALL = install
569
569
TCL_PATH = tclsh
570
570
TCLTK_PATH = wish
571
571
XGETTEXT = xgettext
572
+ MSGCAT = msgcat
572
573
MSGFMT = msgfmt
574
+ MSGMERGE = msgmerge
573
575
CURL_CONFIG = curl-config
574
576
GCOV = gcov
575
577
STRIP = strip
@@ -844,7 +846,7 @@ generated-hdrs: $(GENERATED_H)
844
846
# # Exhaustive lists of our source files, either dynamically generated,
845
847
# # or hardcoded.
846
848
SOURCES_CMD = ( \
847
- git ls-files \
849
+ git ls-files --deduplicate \
848
850
'*.[hcS]' \
849
851
'*.sh' \
850
852
':!*[tp][0-9][0-9][0-9][0-9]*' \
@@ -855,12 +857,13 @@ SOURCES_CMD = ( \
855
857
-o \( -name '[tp][0-9][0-9][0-9][0-9]*' -prune \) \
856
858
-o \( -name contrib -type d -prune \) \
857
859
-o \( -name build -type d -prune \) \
860
+ -o \( -name .build -type d -prune \) \
858
861
-o \( -name 'trash*' -type d -prune \) \
859
862
-o \( -name '*.[hcS]' -type f -print \) \
860
863
-o \( -name '*.sh' -type f -print \) \
861
864
| sed -e 's|^\./||' \
862
865
)
863
- FOUND_SOURCE_FILES := $(shell $(SOURCES_CMD ) )
866
+ FOUND_SOURCE_FILES := $(filter-out $( GENERATED_H ) , $( shell $(SOURCES_CMD ) ) )
864
867
865
868
FOUND_C_SOURCES = $(filter % .c,$(FOUND_SOURCE_FILES ) )
866
869
FOUND_H_SOURCES = $(filter % .h,$(FOUND_SOURCE_FILES ) )
@@ -2708,56 +2711,148 @@ XGETTEXT_FLAGS = \
2708
2711
--force-po \
2709
2712
--add-comments=TRANSLATORS: \
2710
2713
--msgid-bugs-address="Git Mailing List <
[email protected] >"
\
2711
- --from-code=UTF-8
2714
+ --package-name=Git
2712
2715
XGETTEXT_FLAGS_C = $(XGETTEXT_FLAGS ) --language=C \
2713
2716
--keyword=_ --keyword=N_ --keyword="Q_:1,2"
2714
2717
XGETTEXT_FLAGS_SH = $(XGETTEXT_FLAGS ) --language=Shell \
2715
2718
--keyword=gettextln --keyword=eval_gettextln
2716
2719
XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS ) --language=Perl \
2717
2720
--keyword=__ --keyword=N__ --keyword="__n:1,2"
2718
- LOCALIZED_C = $(C_OBJ:o=c ) $(LIB_H ) $(GENERATED_H )
2719
- LOCALIZED_SH = $(SCRIPT_SH )
2720
- LOCALIZED_SH += git-sh-setup.sh
2721
- LOCALIZED_PERL = $(SCRIPT_PERL )
2721
+ MSGMERGE_FLAGS = --add-location --backup=off --update
2722
+ LOCALIZED_C = $(sort $(FOUND_C_SOURCES ) $(FOUND_H_SOURCES ) $(SCALAR_SOURCES ) \
2723
+ $(GENERATED_H ) )
2724
+ LOCALIZED_SH = $(sort $(SCRIPT_SH ) git-sh-setup.sh)
2725
+ LOCALIZED_PERL = $(sort $(SCRIPT_PERL ) )
2722
2726
2723
2727
ifdef XGETTEXT_INCLUDE_TESTS
2724
2728
LOCALIZED_C += t/t0200/test.c
2725
2729
LOCALIZED_SH += t/t0200/test.sh
2726
2730
LOCALIZED_PERL += t/t0200/test.perl
2727
2731
endif
2728
2732
2729
- # # Note that this is meant to be run only by the localization coordinator
2730
- # # under a very controlled condition, i.e. (1) it is to be run in a
2731
- # # Git repository (not a tarball extract), (2) any local modifications
2732
- # # will be lost.
2733
+ # # We generate intermediate .build/pot/po/%.po files containing a
2734
+ # # extract of the translations we find in each file in the source
2735
+ # # tree. We will assemble them using msgcat to create the final
2736
+ # # "po/git.pot" file.
2737
+ LOCALIZED_ALL_GEN_PO =
2738
+
2739
+ LOCALIZED_C_GEN_PO = $(LOCALIZED_C:%=.build/pot/po/%.po )
2740
+ LOCALIZED_ALL_GEN_PO += $(LOCALIZED_C_GEN_PO )
2741
+
2742
+ LOCALIZED_SH_GEN_PO = $(LOCALIZED_SH:%=.build/pot/po/%.po )
2743
+ LOCALIZED_ALL_GEN_PO += $(LOCALIZED_SH_GEN_PO )
2744
+
2745
+ LOCALIZED_PERL_GEN_PO = $(LOCALIZED_PERL:%=.build/pot/po/%.po )
2746
+ LOCALIZED_ALL_GEN_PO += $(LOCALIZED_PERL_GEN_PO )
2747
+
2733
2748
# # Gettext tools cannot work with our own custom PRItime type, so
2734
2749
# # we replace PRItime with PRIuMAX. We need to update this to
2735
2750
# # PRIdMAX if we switch to a signed type later.
2751
+ $(LOCALIZED_C_GEN_PO ) : .build/pot/po/% .po: %
2752
+ $(call mkdir_p_parent_template)
2753
+ $(QUIET_XGETTEXT ) \
2754
+ if grep -q PRItime $< ; then \
2755
+ (\
2756
+ sed -e ' s|PRItime|PRIuMAX|g' < $< \
2757
+ > .build/pot/po/$< && \
2758
+ cd .build/pot/po && \
2759
+ $(XGETTEXT ) --omit-header \
2760
+ -o $(@:.build/pot/po/%=% ) \
2761
+ $(XGETTEXT_FLAGS_C ) $< && \
2762
+ rm $< ; \
2763
+ ); \
2764
+ else \
2765
+ $(XGETTEXT ) --omit-header \
2766
+ -o $@ $(XGETTEXT_FLAGS_C ) $< ; \
2767
+ fi
2736
2768
2737
- po/git.pot : $( GENERATED_H ) FORCE
2738
- # All modifications will be reverted at the end, so we do not
2739
- # want to have any local change.
2740
- git diff --quiet HEAD && git diff --quiet --cached
2769
+ $( LOCALIZED_SH_GEN_PO ) : .build/pot/ po/% .po: %
2770
+ $( call mkdir_p_parent_template)
2771
+ $( QUIET_XGETTEXT )$( XGETTEXT ) --omit-header \
2772
+ -o $@ $( XGETTEXT_FLAGS_SH ) $<
2741
2773
2742
- @for s in $(LOCALIZED_C) $(LOCALIZED_SH) $(LOCALIZED_PERL); \
2743
- do \
2744
- sed -e 's|PRItime|PRIuMAX|g' <"$$s" >"$$s+" && \
2745
- cat "$$s+" >"$$s" && rm "$$s+"; \
2746
- done
2774
+ $(LOCALIZED_PERL_GEN_PO ) : .build/pot/po/% .po: %
2775
+ $(call mkdir_p_parent_template)
2776
+ $(QUIET_XGETTEXT )$(XGETTEXT ) --omit-header \
2777
+ -o$@ $(XGETTEXT_FLAGS_PERL ) $<
2778
+
2779
+ define gen_pot_header
2780
+ $(XGETTEXT ) $(XGETTEXT_FLAGS_C ) \
2781
+ -o - /dev/null | \
2782
+ sed -e 's|charset=CHARSET|charset=UTF-8|' \
2783
+ -e 's|\(Last-Translator: \)FULL NAME <.*>|\1make by the Makefile|' \
2784
+ -e 's|\(Language-Team: \)LANGUAGE <.*>|\1Git Mailing List <
[email protected] >|' \
2785
+ >$@ && \
2786
+ echo '"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\\n"' >>$@
2787
+ endef
2747
2788
2748
- $(QUIET_XGETTEXT)$(XGETTEXT) -o$@+ $(XGETTEXT_FLAGS_C) $(LOCALIZED_C)
2749
- $(QUIET_XGETTEXT)$(XGETTEXT) -o$@+ --join-existing $(XGETTEXT_FLAGS_SH) \
2750
- $(LOCALIZED_SH)
2751
- $(QUIET_XGETTEXT)$(XGETTEXT) -o$@+ --join-existing $(XGETTEXT_FLAGS_PERL) \
2752
- $(LOCALIZED_PERL)
2789
+ .build/pot/git.header : $(LOCALIZED_ALL_GEN_PO )
2790
+ $(call mkdir_p_parent_template)
2791
+ $(QUIET_GEN )$(gen_pot_header )
2753
2792
2754
- # Reverting the munged source, leaving only the updated $@
2755
- git reset --hard
2756
- mv $@+ $@
2793
+ po/git.pot : .build/pot/git.header $(LOCALIZED_ALL_GEN_PO )
2794
+ $(QUIET_GEN )$(MSGCAT ) $^ > $@
2757
2795
2758
2796
.PHONY : pot
2759
2797
pot : po/git.pot
2760
2798
2799
+ define check_po_file_envvar
2800
+ $(if $(PO_FILE ) , \
2801
+ $(if $(filter po/% .po,$(PO_FILE ) ) , , \
2802
+ $(error PO_FILE should match pattern: "po/% .po") ) , \
2803
+ $(error PO_FILE is not defined) )
2804
+ endef
2805
+
2806
+ .PHONY : po-update
2807
+ po-update : po/git.pot
2808
+ $(check_po_file_envvar )
2809
+ @if test ! -e $(PO_FILE ) ; then \
2810
+ echo >&2 " error: $( PO_FILE) does not exist" ; \
2811
+ echo >&2 ' To create an initial po file, use: "make po-init PO_FILE=po/XX.po"' ; \
2812
+ exit 1; \
2813
+ fi
2814
+ $(QUIET_MSGMERGE )$(MSGMERGE ) $(MSGMERGE_FLAGS ) $(PO_FILE ) po/git.pot
2815
+
2816
+ .PHONY : check-pot
2817
+ check-pot : $(LOCALIZED_ALL_GEN_PO )
2818
+
2819
+ # ## TODO FIXME: Translating everything in these files is a bad
2820
+ # ## heuristic for "core", as we'll translate obscure error() messages
2821
+ # ## along with commonly seen i18n messages. A better heuristic would
2822
+ # ## be to e.g. use spatch to first remove error/die/warning
2823
+ # ## etc. messages.
2824
+ LOCALIZED_C_CORE =
2825
+ LOCALIZED_C_CORE += builtin/checkout.c
2826
+ LOCALIZED_C_CORE += builtin/clone.c
2827
+ LOCALIZED_C_CORE += builtin/index-pack.c
2828
+ LOCALIZED_C_CORE += builtin/push.c
2829
+ LOCALIZED_C_CORE += builtin/reset.c
2830
+ LOCALIZED_C_CORE += remote.c
2831
+ LOCALIZED_C_CORE += wt-status.c
2832
+
2833
+ LOCALIZED_C_CORE_GEN_PO = $(LOCALIZED_C_CORE:%=.build/pot/po/%.po )
2834
+
2835
+ .build/pot/git-core.header : $(LOCALIZED_C_CORE_GEN_PO )
2836
+ $(call mkdir_p_parent_template)
2837
+ $(QUIET_GEN )$(gen_pot_header )
2838
+
2839
+ po/git-core.pot : .build/pot/git-core.header $(LOCALIZED_C_CORE_GEN_PO )
2840
+ $(QUIET_GEN )$(MSGCAT ) $^ > $@
2841
+
2842
+ .PHONY : po-init
2843
+ po-init : po/git-core.pot
2844
+ $(check_po_file_envvar )
2845
+ @if test -e $(PO_FILE ) ; then \
2846
+ echo >&2 " error: $( PO_FILE) exists already" ; \
2847
+ exit 1; \
2848
+ fi
2849
+ $(QUIET_MSGINIT ) msginit \
2850
+ --input=$< \
2851
+ --output=$(PO_FILE ) \
2852
+ --no-translator \
2853
+ --locale=$(PO_FILE:po/%.po=% )
2854
+
2855
+ # # po/*.po files & their rules
2761
2856
ifdef NO_GETTEXT
2762
2857
POFILES :=
2763
2858
MOFILES :=
@@ -3293,6 +3388,8 @@ cocciclean:
3293
3388
$(RM ) contrib/coccinelle/* .cocci.patch*
3294
3389
3295
3390
clean : profile-clean coverage-clean cocciclean
3391
+ $(RM ) -r .build
3392
+ $(RM ) po/git.pot po/git-core.pot
3296
3393
$(RM ) * .res
3297
3394
$(RM ) $(OBJECTS )
3298
3395
$(RM ) $(LIB_FILE ) $(XDIFF_LIB ) $(REFTABLE_LIB ) $(REFTABLE_TEST_LIB )
0 commit comments