Maintenance: Shebang lines fix for some python scripts
[blender.git] / release / scripts / modules / bl_i18n_utils / merge_po.py
1 #!/usr/bin/env python3
2
3 # ***** BEGIN GPL LICENSE BLOCK *****
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software Foundation,
17 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 #
19 # ***** END GPL LICENSE BLOCK *****
20
21 # <pep8 compliant>
22
23 # Merge one or more .po files into the first dest one.
24 # If a msgkey is present in more than one merged po, the one in the first file wins, unless
25 # it’s marked as fuzzy and one later is not.
26 # The fuzzy flag is removed if necessary.
27 # All other comments are never modified.
28 # However, commented messages in dst will always remain commented, and commented messages are
29 # never merged from sources.
30
31 import sys
32
33 try:
34     import settings
35     import utils
36 except:
37     from . import (settings, utils)
38
39
40 # XXX This is a quick hack to make it work with new I18n... objects! To be reworked!
41 def main():
42     import argparse
43     parser = argparse.ArgumentParser(description=""
44                     "Merge one or more .po files into the first dest one.\n"
45                     "If a msgkey (msgctxt, msgid) is present in more than one merged po, the one in the first file "
46                     "wins, unless it’s marked as fuzzy and one later is not.\n"
47                     "The fuzzy flag is removed if necessary.\n"
48                     "All other comments are never modified.\n"
49                     "Commented messages in dst will always remain commented, and commented messages are never merged "
50                     "from sources.")
51     parser.add_argument('-s', '--stats', action="store_true", help="Show statistics info.")
52     parser.add_argument('-r', '--replace', action="store_true",
53                         help="Replace existing messages of same \"level\" already in dest po.")
54     parser.add_argument('dst', metavar='dst.po', help="The dest po into which merge the others.")
55     parser.add_argument('src', metavar='src.po', nargs='+', help="The po's to merge into the dst.po one.")
56     args = parser.parse_args()
57
58     ret = 0
59     done_msgkeys = set()
60     done_fuzzy_msgkeys = set()
61     nbr_merged = 0
62     nbr_replaced = 0
63     nbr_added = 0
64     nbr_unfuzzied = 0
65
66     dst_msgs = utils.I18nMessages(kind='PO', src=args.dst)
67     if dst_msgs.parsing_errors:
68         print("Dest po is BROKEN, aborting.")
69         return 1
70     if args.stats:
71         print("Dest po, before merging:")
72         dst_msgs.print_stats(prefix="\t")
73     # If we don’t want to replace existing valid translations, pre-populate done_msgkeys and done_fuzzy_msgkeys.
74     if not args.replace:
75         done_msgkeys = dst_msgs.trans_msgs.copy()
76         done_fuzzy_msgkeys = dst_msgs.fuzzy_msgs.copy()
77     for po in args.src:
78         msgs = utils.I18nMessages(kind='PO', src=po)
79         if msgs.parsing_errors:
80             print("\tSrc po {} is BROKEN, skipping.".format(po))
81             ret = 1
82             continue
83         print("\tMerging {}...".format(po))
84         if args.stats:
85             print("\t\tMerged po stats:")
86             msgs.print_stats(prefix="\t\t\t")
87         for msgkey, msg in msgs.msgs.items():
88             msgctxt, msgid = msgkey
89             # This msgkey has already been completely merged, or is a commented one,
90             # or the new message is commented, skip it.
91             if msgkey in (done_msgkeys | dst_msgs.comm_msgs | msgs.comm_msgs):
92                 continue
93             is_ttip = msg.is_tooltip
94             # New messages does not yet exists in dest.
95             if msgkey not in dst_msgs.msgs:
96                 dst_msgs[msgkey] = msgs.msgs[msgkey]
97                 if msgkey in msgs.fuzzy_msgs:
98                     done_fuzzy_msgkeys.add(msgkey)
99                     dst_msgs.fuzzy_msgs.add(msgkey)
100                 elif msgkey in msgs.trans_msgs:
101                     done_msgkeys.add(msgkey)
102                     dst_msgs.trans_msgs.add(msgkey)
103                 nbr_added += 1
104             # From now on, the new messages is already in dst.
105             # New message is neither translated nor fuzzy, skip it.
106             elif msgkey not in (msgs.trans_msgs | msgs.fuzzy_msgs):
107                 continue
108             # From now on, the new message is either translated or fuzzy!
109             # The new message is translated.
110             elif msgkey in msgs.trans_msgs:
111                 dst_msgs.msgs[msgkey].msgstr = msg.msgstr
112                 done_msgkeys.add(msgkey)
113                 done_fuzzy_msgkeys.discard(msgkey)
114                 if msgkey in dst_msgs.fuzzy_msgs:
115                     dst_msgs.fuzzy_msgs.remove(msgkey)
116                     nbr_unfuzzied += 1
117                 if msgkey not in dst_msgs.trans_msgs:
118                     dst_msgs.trans_msgs.add(msgkey)
119                 else:
120                     nbr_replaced += 1
121                 nbr_merged += 1
122             # The new message is fuzzy, org one is fuzzy too, and this msgkey has not yet been merged.
123             elif msgkey not in (dst_msgs.trans_msgs | done_fuzzy_msgkeys):
124                 dst_msgs[msgkey].msgstr = msg.msgstr
125                 done_fuzzy_msgkeys.add(msgkey)
126                 dst_msgs.fuzzy_msgs.add(msgkey)
127                 nbr_merged += 1
128                 nbr_replaced += 1
129
130     dst_msgs.write(kind='PO', dest=args.dst)
131
132     print("Merged completed. {} messages were merged (among which {} were replaced), {} were added, "
133           "{} were \"un-fuzzied\".".format(nbr_merged, nbr_replaced, nbr_added, nbr_unfuzzied))
134     if args.stats:
135         dst_msgs.update_info()
136         print("Final merged po stats:")
137         dst_msgs.print_stats(prefix="\t")
138     return ret
139
140
141 if __name__ == "__main__":
142     print("\n\n *** Running {} *** \n".format(__file__))
143     sys.exit(main())