2 # SPDX-License-Identifier: GPL-2.0
5 This script helps track the translation status of the documentation
6 in different locales, e.g., zh_CN. More specially, it uses `git log`
7 commit to find the latest english commit from the translation commit
8 (order by author date) and the latest english commits from HEAD. If
9 differences occur, report the file and commits that need to be updated.
11 The usage is as follows:
12 - ./scripts/checktransupdate.py -l zh_CN
13 This will print all the files that need to be updated in the zh_CN locale.
14 - ./scripts/checktransupdate.py Documentation/translations/zh_CN/dev-tools/testing-overview.rst
15 This will only print the status of the specified file.
17 The output is something like:
18 Documentation/translations/zh_CN/dev-tools/testing-overview.rst (1 commits)
19 commit 42fb9cfd5b18 ("Documentation: dev-tools: Add link to RV docs")
23 from argparse import ArgumentParser, BooleanOptionalAction
24 from datetime import datetime
31 def dprint(*args, **kwargs):
33 print("[DEBUG] ", end="")
34 print(*args, **kwargs)
37 def get_origin_path(file_path):
38 paths = file_path.split("/")
39 tidx = paths.index("translations")
41 opaths += paths[tidx + 2 :]
42 return "/".join(opaths)
45 def get_latest_commit_from(file_path, commit):
46 command = "git log --pretty=format:%H%n%aD%n%cD%n%n%B {} -1 -- {}".format(
50 pipe = os.popen(command)
52 result = result.split("\n")
56 dprint("Result: {}".format(result[0]))
60 "author_date": datetime.strptime(result[1], "%a, %d %b %Y %H:%M:%S %z"),
61 "commit_date": datetime.strptime(result[2], "%a, %d %b %Y %H:%M:%S %z"),
62 "message": result[4:],
66 def get_origin_from_trans(origin_path, t_from_head):
67 o_from_t = get_latest_commit_from(origin_path, t_from_head["hash"])
68 while o_from_t is not None and o_from_t["author_date"] > t_from_head["author_date"]:
69 o_from_t = get_latest_commit_from(origin_path, o_from_t["hash"] + "^")
70 if o_from_t is not None:
71 dprint("tracked origin commit id: {}".format(o_from_t["hash"]))
75 def get_commits_count_between(opath, commit1, commit2):
76 command = "git log --pretty=format:%H {}...{} -- {}".format(commit1, commit2, opath)
78 pipe = os.popen(command)
79 result = pipe.read().split("\n")
80 # filter out empty lines
81 result = list(filter(lambda x: x != "", result))
85 def pretty_output(commit):
86 command = "git log --pretty='format:%h (\"%s\")' -1 {}".format(commit)
88 pipe = os.popen(command)
92 def check_per_file(file_path):
93 opath = get_origin_path(file_path)
95 if not os.path.isfile(opath):
96 dprint("Error: Cannot find the origin path for {}".format(file_path))
99 o_from_head = get_latest_commit_from(opath, "HEAD")
100 t_from_head = get_latest_commit_from(file_path, "HEAD")
102 if o_from_head is None or t_from_head is None:
103 print("Error: Cannot find the latest commit for {}".format(file_path))
106 o_from_t = get_origin_from_trans(opath, t_from_head)
109 print("Error: Cannot find the latest origin commit for {}".format(file_path))
112 if o_from_head["hash"] == o_from_t["hash"]:
114 print("No update needed for {}".format(file_path))
117 print("{}".format(file_path), end="\t")
118 commits = get_commits_count_between(
119 opath, o_from_t["hash"], o_from_head["hash"]
121 print("({} commits)".format(len(commits)))
123 for commit in commits:
124 msg = pretty_output(commit)
125 if "Merge tag" not in msg:
130 script_path = os.path.dirname(os.path.abspath(__file__))
131 linux_path = os.path.join(script_path, "..")
133 parser = ArgumentParser(description="Check the translation update")
137 help="Locale to check when files are not specified",
141 action=BooleanOptionalAction,
143 help="Print commits between the origin and the translation",
147 "--print-updated-files",
148 action=BooleanOptionalAction,
150 help="Print files that do no need to be updated",
155 action=BooleanOptionalAction,
156 help="Print debug information",
161 "files", nargs="*", help="Files to check, if not specified, check all files"
163 args = parser.parse_args()
165 global flag_p_c, flag_p_uf, flag_debug
166 flag_p_c = args.print_commits
167 flag_p_uf = args.print_updated_files
168 flag_debug = args.debug
170 # get files related to linux path
173 if args.locale is not None:
176 "find {}/Documentation/translations/{} -type f".format(
177 linux_path, args.locale
186 "find {}/Documentation/translations -type f".format(linux_path)
192 files = list(filter(lambda x: x != "", files))
193 files = list(map(lambda x: os.path.relpath(os.path.abspath(x), linux_path), files))
195 # cd to linux root directory
202 if __name__ == "__main__":