diff options
Diffstat (limited to 'editor/translations/extract.py')
-rwxr-xr-x | editor/translations/extract.py | 187 |
1 files changed, 67 insertions, 120 deletions
diff --git a/editor/translations/extract.py b/editor/translations/extract.py index 8737eb5204..bd32fc01c7 100755 --- a/editor/translations/extract.py +++ b/editor/translations/extract.py @@ -3,12 +3,47 @@ import enum import fnmatch import os +import os.path import re import shutil import subprocess import sys +class Message: + __slots__ = ("msgid", "msgid_plural", "msgctxt", "comments", "locations") + + def format(self): + lines = [] + + if self.comments: + for i, content in enumerate(self.comments): + prefix = "#. TRANSLATORS:" if i == 0 else "#." + lines.append(prefix + content) + + lines.append("#: " + " ".join(self.locations)) + + if self.msgctxt: + lines.append('msgctxt "{}"'.format(self.msgctxt)) + + if self.msgid_plural: + lines += [ + 'msgid "{}"'.format(self.msgid), + 'msgid_plural "{}"'.format(self.msgid_plural), + 'msgstr[0] ""', + 'msgstr[1] ""', + ] + else: + lines += [ + 'msgid "{}"'.format(self.msgid), + 'msgstr ""', + ] + + return "\n".join(lines) + + +messages_map = {} # (id, context) -> Message. + line_nb = False for arg in sys.argv[1:]: @@ -42,9 +77,6 @@ with open("editor/editor_property_name_processor.cpp") as f: remaps[m.group("from")] = m.group("to") -unique_str = [] -unique_loc = {} -ctx_group = {} # Store msgctx, msg, and locations. main_po = """ # LANGUAGE translation of the Godot Engine editor. # Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. @@ -82,15 +114,23 @@ message_patterns = { r'RTRN\("(?P<message>([^"\\]|\\.)*)", "(?P<plural_message>([^"\\]|\\.)*)",[^,)]+?(, "(?P<context>([^"\\]|\\.)*)")?\)' ): ExtractType.TEXT, re.compile(r'_initial_set\("(?P<message>[^"]+?)",'): ExtractType.PROPERTY_PATH, - re.compile(r'GLOBAL_DEF(_RST)?(_NOVAL)?\("(?P<message>[^".]+?)",'): ExtractType.PROPERTY_PATH, + re.compile(r'GLOBAL_DEF(_RST)?(_NOVAL)?(_BASIC)?\("(?P<message>[^"]+?)",'): ExtractType.PROPERTY_PATH, + re.compile(r'GLOBAL_DEF_BASIC\(vformat\("(?P<message>layer_names/\w+)/layer_%d"'): ExtractType.PROPERTY_PATH, re.compile(r'EDITOR_DEF(_RST)?\("(?P<message>[^"]+?)",'): ExtractType.PROPERTY_PATH, re.compile( + r'EDITOR_SETTING(_USAGE)?\(Variant::[_A-Z0-9]+, [_A-Z0-9]+, "(?P<message>[^"]+?)",' + ): ExtractType.PROPERTY_PATH, + re.compile( r'(ADD_PROPERTYI?|ImportOption|ExportOption)\(PropertyInfo\(Variant::[_A-Z0-9]+, "(?P<message>[^"]+?)"[,)]' ): ExtractType.PROPERTY_PATH, re.compile( r"(?!#define )LIMPL_PROPERTY(_RANGE)?\(Variant::[_A-Z0-9]+, (?P<message>[^,]+?)," ): ExtractType.PROPERTY_PATH, re.compile(r'ADD_GROUP\("(?P<message>[^"]+?)", "(?P<prefix>[^"]*?)"\)'): ExtractType.GROUP, + re.compile(r'#define WRTC_\w+ "(?P<message>[^"]+?)"'): ExtractType.PROPERTY_PATH, +} +theme_property_patterns = { + re.compile(r'set_(constant|font|font_size|stylebox|color|icon)\("(?P<message>[^"]+)", '): ExtractType.PROPERTY_PATH, } @@ -119,95 +159,6 @@ def _process_editor_string(name): return " ".join(capitalized_parts) -def _write_message(msgctx, msg, msg_plural, location): - global main_po - main_po += "#: " + location + "\n" - if msgctx != "": - main_po += 'msgctxt "' + msgctx + '"\n' - main_po += 'msgid "' + msg + '"\n' - if msg_plural != "": - main_po += 'msgid_plural "' + msg_plural + '"\n' - main_po += 'msgstr[0] ""\n' - main_po += 'msgstr[1] ""\n\n' - else: - main_po += 'msgstr ""\n\n' - - -def _add_additional_location(msgctx, msg, location): - global main_po - # Add additional location to previous occurrence. - if msgctx != "": - msg_pos = main_po.find('\nmsgctxt "' + msgctx + '"\nmsgid "' + msg + '"') - else: - msg_pos = main_po.find('\nmsgid "' + msg + '"') - - if msg_pos == -1: - print("Someone apparently thought writing Python was as easy as GDScript. Ping Akien.") - main_po = main_po[:msg_pos] + " " + location + main_po[msg_pos:] - - -def _write_translator_comment(msgctx, msg, translator_comment): - if translator_comment == "": - return - - global main_po - if msgctx != "": - msg_pos = main_po.find('\nmsgctxt "' + msgctx + '"\nmsgid "' + msg + '"') - else: - msg_pos = main_po.find('\nmsgid "' + msg + '"') - - # If it's a new message, just append comment to the end of PO file. - if msg_pos == -1: - main_po += _format_translator_comment(translator_comment, True) - return - - # Find position just before location. Translator comment will be added there. - translator_comment_pos = main_po.rfind("\n\n#", 0, msg_pos) + 2 - if translator_comment_pos - 2 == -1: - print("translator_comment_pos not found") - return - - # Check if a previous translator comment already exists. If so, merge them together. - if main_po.find("TRANSLATORS:", translator_comment_pos, msg_pos) != -1: - translator_comment_pos = main_po.find("\n#:", translator_comment_pos, msg_pos) + 1 - if translator_comment_pos == 0: - print('translator_comment_pos after "TRANSLATORS:" not found') - return - main_po = ( - main_po[:translator_comment_pos] - + _format_translator_comment(translator_comment, False) - + main_po[translator_comment_pos:] - ) - return - - main_po = ( - main_po[:translator_comment_pos] - + _format_translator_comment(translator_comment, True) - + main_po[translator_comment_pos:] - ) - - -def _format_translator_comment(comment, new): - if not comment: - return "" - - comment_lines = comment.split("\n") - - formatted_comment = "" - if not new: - for comment in comment_lines: - formatted_comment += "#. " + comment.strip() + "\n" - return formatted_comment - - formatted_comment = "#. TRANSLATORS: " - for i in range(len(comment_lines)): - if i == 0: - formatted_comment += comment_lines[i].strip() + "\n" - else: - formatted_comment += "#. " + comment_lines[i].strip() + "\n" - return formatted_comment - - def _is_block_translator_comment(translator_line): line = translator_line.strip() if line.find("//") == 0: @@ -253,6 +204,10 @@ def process_file(f, fname): translator_comment = "" current_group = "" + patterns = message_patterns + if os.path.basename(fname) == "default_theme.cpp": + patterns = {**message_patterns, **theme_property_patterns} + while l: # Detect translator comments. @@ -270,7 +225,7 @@ def process_file(f, fname): translator_comment = translator_comment[:-1] # Remove extra \n at the end. if not reading_translator_comment: - for pattern, extract_type in message_patterns.items(): + for pattern, extract_type in patterns.items(): for m in pattern.finditer(l): location = os.path.relpath(fname).replace("\\", "/") if line_nb: @@ -289,6 +244,8 @@ def process_file(f, fname): msg = msg[len(current_group) :] else: current_group = "" + if "." in msg: # Strip feature tag. + msg = msg.split(".", 1)[0] for part in msg.split("/"): _add_message(_process_editor_string(part), msg_plural, msgctx, location, translator_comment) elif extract_type == ExtractType.GROUP: @@ -301,32 +258,20 @@ def process_file(f, fname): def _add_message(msg, msg_plural, msgctx, location, translator_comment): - global main_po, unique_str, unique_loc - - # Write translator comment. - _write_translator_comment(msgctx, msg, translator_comment) - translator_comment = "" - - if msgctx != "": - # If it's a new context or a new message within an existing context, then write new msgid. - # Else add location to existing msgid. - if not msgctx in ctx_group: - _write_message(msgctx, msg, msg_plural, location) - ctx_group[msgctx] = {msg: [location]} - elif not msg in ctx_group[msgctx]: - _write_message(msgctx, msg, msg_plural, location) - ctx_group[msgctx][msg] = [location] - elif not location in ctx_group[msgctx][msg]: - _add_additional_location(msgctx, msg, location) - ctx_group[msgctx][msg].append(location) - else: - if not msg in unique_str: - _write_message(msgctx, msg, msg_plural, location) - unique_str.append(msg) - unique_loc[msg] = [location] - elif not location in unique_loc[msg]: - _add_additional_location(msgctx, msg, location) - unique_loc[msg].append(location) + key = (msg, msgctx) + message = messages_map.get(key) + if not message: + message = Message() + message.msgid = msg + message.msgid_plural = msg_plural + message.msgctxt = msgctx + message.locations = [] + message.comments = [] + messages_map[key] = message + if location not in message.locations: + message.locations.append(location) + if translator_comment and translator_comment not in message.comments: + message.comments.append(translator_comment) print("Updating the editor.pot template...") @@ -335,6 +280,8 @@ for fname in matches: with open(fname, "r", encoding="utf8") as f: process_file(f, fname) +main_po += "\n\n".join(message.format() for message in messages_map.values()) + with open("editor.pot", "w") as f: f.write(main_po) |