a1fe20f9fce2360869ca9e34b4e851c3907dc444
[blender.git] / release / scripts / modules / bl_i18n_utils / update_po.py
1 #!/usr/bin/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 # Update po’s in the branches from blender.pot in /trunk/po dir.
24
25 import subprocess
26 import os
27 import sys
28 from codecs import open
29 import shutil
30
31 try:
32     import settings
33     import utils
34 except:
35     from . import (settings, utils)
36
37
38 GETTEXT_MSGMERGE_EXECUTABLE = settings.GETTEXT_MSGMERGE_EXECUTABLE
39 BRANCHES_DIR = settings.BRANCHES_DIR
40 TRUNK_PO_DIR = settings.TRUNK_PO_DIR
41 FILE_NAME_POT = settings.FILE_NAME_POT
42
43
44 # XXX Not updated, not sure it's that much useful...
45 def pproc_newcontext_po(po, pot_messages, pot_stats):
46     print("Adding new contexts to {}...".format(po))
47     messages, state, stats = utils.parse_messages(po)
48     known_ctxt = stats["contexts"]
49     print("Already known (present) context(s): {}".format(str(known_ctxt)))
50
51     new_ctxt = set()
52     added = 0
53     # Only use valid already translated messages!
54     allowed_keys = state["trans_msg"] - state["fuzzy_msg"] - state["comm_msg"]
55     for key in pot_messages.keys():
56         ctxt, msgid = key
57         if ctxt in known_ctxt:
58             continue
59         new_ctxt.add(ctxt)
60         for t_ctxt in known_ctxt:
61             # XXX The first match will win, this might not be optimal...
62             t_key = (t_ctxt, msgid)
63             if t_key in allowed_keys:
64                 # Wrong comments (sources) will be removed by msgmerge...
65                 messages[key] = messages[t_key]
66                 messages[key]["msgctxt_lines"] = [ctxt]
67                 added += 1
68
69     utils.write_messages(po, messages, state["comm_msg"], state["fuzzy_msg"])
70     print("Finished!\n    {} new context(s) was/were added {}, adding {} new "
71           "messages.\n".format(len(new_ctxt), str(new_ctxt), added))
72     return 0
73
74
75 def process_po(po, lang):
76     # update po file
77     #cmd = (GETTEXT_MSGMERGE_EXECUTABLE,
78            #"--update",
79            #"-w", "1",  # XXX Ugly hack to prevent msgmerge merging short source comments together!
80            #"--no-wrap",
81            #"--backup=none",
82            #"--lang={}".format(lang),
83            #po,
84            #FILE_NAME_POT,
85            #)
86
87     pot = utils.I18nMessages(kind='PO', src=FILE_NAME_POT)
88     msg = utils.I18nMessages(iso=lang, kind='PO', src=po)
89     print("Updating {}...".format(po))
90     msg.update(pot)
91     msg.write(kind='PO', dest=po)
92     #print("Running ", " ".join(cmd))
93     #ret = subprocess.call(cmd)
94     print("Finished!\n")
95     return 0
96
97
98 def main():
99     import argparse
100     parser = argparse.ArgumentParser(description="Write out messages.txt "
101                                                  "from Blender.")
102     parser.add_argument('-t', '--trunk', action="store_true", help="Update po’s in /trunk/po rather than /branches.")
103     parser.add_argument('-i', '--input', metavar="File", help="Input pot file path.")
104     #parser.add_argument('--pproc-contexts', action="store_true",
105                         #help="Pre-process po’s to avoid having plenty of fuzzy msgids just because a context was "
106                              #"added/changed!")
107     parser.add_argument('-a', '--add', action="store_true",
108                         help="Add missing po’s (useful only when one or more languages are given!).")
109     parser.add_argument('langs', metavar='ISO_code', nargs='*', help="Restrict processed languages to those.")
110     args = parser.parse_args()
111
112     if args.input:
113         global FILE_NAME_POT
114         FILE_NAME_POT = args.input
115     ret = 0
116
117     #if args.pproc_contexts:
118         #_ctxt_proc = pproc_newcontext_po
119         #pot_messages, _a, pot_stats = utils.parse_messages(FILE_NAME_POT)
120     if 0:
121         pass
122     else:
123         _ctxt_proc = lambda a, b, c: 0
124         pot_messages, pot_stats = None, None
125
126     if args.langs:
127         for lang in args.langs:
128             if args.trunk:
129                 dr = TRUNK_PO_DIR
130                 po = os.path.join(dr, ".".join((lang, "po")))
131             else:
132                 dr = os.path.join(BRANCHES_DIR, lang)
133                 po = os.path.join(dr, ".".join((lang, "po")))
134             if args.add:
135                 if not os.path.exists(dr):
136                     os.makedirs(dr)
137                 if not os.path.exists(po):
138                     shutil.copy(FILE_NAME_POT, po)
139             if args.add or os.path.exists(po):
140                 t = _ctxt_proc(po, pot_messages, pot_stats)
141                 if t:
142                     ret = t
143                 t = process_po(po, lang)
144                 if t:
145                     ret = t
146     elif args.trunk:
147         for po in os.listdir(TRUNK_PO_DIR):
148             if po.endswith(".po"):
149                 lang = os.path.basename(po)[:-3]
150                 po = os.path.join(TRUNK_PO_DIR, po)
151                 t = _ctxt_proc(po, pot_messages, pot_stats)
152                 if t:
153                     ret = t
154                 t = process_po(po, lang)
155                 if t:
156                     ret = t
157     else:
158         for lang in os.listdir(BRANCHES_DIR):
159             po = os.path.join(BRANCHES_DIR, lang, ".".join((lang, "po")))
160             if os.path.exists(po):
161                 t = _ctxt_proc(po, pot_messages, pot_stats)
162                 if t:
163                     ret = t
164                 t = process_po(po, lang)
165                 if t:
166                     ret = t
167
168     return ret
169
170
171 if __name__ == "__main__":
172     print("\n\n *** Running {} *** \n".format(__file__))
173     sys.exit(main())