summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/editor_feature_profile.cpp4
-rw-r--r--editor/editor_inspector.cpp13
-rw-r--r--editor/editor_node.cpp5
-rw-r--r--editor/editor_property_name_processor.cpp121
-rw-r--r--editor/editor_property_name_processor.h58
-rw-r--r--editor/editor_sectioned_inspector.cpp4
-rw-r--r--editor/editor_settings_dialog.cpp4
-rwxr-xr-xeditor/translations/extract.py172
8 files changed, 294 insertions, 87 deletions
diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp
index 008c42b3a7..b1708e756a 100644
--- a/editor/editor_feature_profile.cpp
+++ b/editor/editor_feature_profile.cpp
@@ -34,6 +34,7 @@
#include "core/io/json.h"
#include "editor/editor_file_dialog.h"
#include "editor/editor_node.h"
+#include "editor/editor_property_name_processor.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
@@ -617,7 +618,8 @@ void EditorFeatureProfileManager::_class_list_item_selected() {
property->set_editable(0, true);
property->set_selectable(0, true);
property->set_checked(0, !edited->is_class_property_disabled(class_name, name));
- property->set_text(0, name.capitalize());
+ property->set_text(0, EditorPropertyNameProcessor::get_singleton()->process_name(name));
+ property->set_tooltip(0, EditorPropertyNameProcessor::get_singleton()->make_tooltip_for_name(name));
property->set_metadata(0, name);
String icon_type = Variant::get_type_name(E.type);
property->set_icon(0, EditorNode::get_singleton()->get_class_icon(icon_type));
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index d48ca7f3b3..f5d318a227 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -36,6 +36,7 @@
#include "editor/doc_tools.h"
#include "editor/editor_feature_profile.h"
#include "editor/editor_node.h"
+#include "editor/editor_property_name_processor.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "multi_node_edit.h"
@@ -2680,10 +2681,10 @@ void EditorInspector::update_tree() {
if (dot != -1) {
String ov = property_label_string.substr(dot);
property_label_string = property_label_string.substr(0, dot);
- property_label_string = property_label_string.capitalize();
+ property_label_string = EditorPropertyNameProcessor::get_singleton()->process_name(property_label_string);
property_label_string += ov;
} else {
- property_label_string = property_label_string.capitalize();
+ property_label_string = EditorPropertyNameProcessor::get_singleton()->process_name(property_label_string);
}
}
@@ -2734,13 +2735,15 @@ void EditorInspector::update_tree() {
current_vbox->add_child(section);
sections.push_back(section);
+ String label = component;
if (capitalize_paths) {
- component = component.capitalize();
+ label = EditorPropertyNameProcessor::get_singleton()->process_name(label);
}
Color c = sscolor;
c.a /= level;
- section->setup(acc_path, component, object, c, use_folding, section_depth);
+ section->setup(acc_path, label, object, c, use_folding, section_depth);
+ section->set_tooltip(EditorPropertyNameProcessor::get_singleton()->make_tooltip_for_name(component));
// Add editors at the start of a group.
for (Ref<EditorInspectorPlugin> &ped : valid_plugins) {
@@ -2772,7 +2775,7 @@ void EditorInspector::update_tree() {
editor_inspector_array = memnew(EditorInspectorArray);
String array_label = path.contains("/") ? path.substr(path.rfind("/") + 1) : path;
- array_label = property_label_string.capitalize();
+ array_label = EditorPropertyNameProcessor::get_singleton()->process_name(property_label_string);
int page = per_array_page.has(array_element_prefix) ? per_array_page[array_element_prefix] : 0;
editor_inspector_array->setup_with_move_element_function(object, array_label, array_element_prefix, page, c, use_folding);
editor_inspector_array->connect("page_change_request", callable_mp(this, &EditorInspector::_page_change_request), varray(array_element_prefix));
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 2c39dc69b9..17b219f8dc 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -90,6 +90,7 @@
#include "editor/editor_paths.h"
#include "editor/editor_plugin.h"
#include "editor/editor_properties.h"
+#include "editor/editor_property_name_processor.h"
#include "editor/editor_resource_picker.h"
#include "editor/editor_resource_preview.h"
#include "editor/editor_run.h"
@@ -5803,6 +5804,9 @@ void EditorNode::notify_settings_changed() {
}
EditorNode::EditorNode() {
+ EditorPropertyNameProcessor *epnp = memnew(EditorPropertyNameProcessor);
+ add_child(epnp);
+
Input::get_singleton()->set_use_accumulated_input(true);
Resource::_get_local_scene_func = _resource_get_edited_scene;
@@ -6025,6 +6029,7 @@ EditorNode::EditorNode() {
EDITOR_DEF("interface/editor/save_on_focus_loss", false);
EDITOR_DEF("interface/editor/show_update_spinner", false);
EDITOR_DEF("interface/editor/update_continuously", false);
+ EDITOR_DEF("interface/editor/translate_properties", true);
EDITOR_DEF_RST("interface/scene_tabs/restore_scenes_on_load", true);
EDITOR_DEF_RST("interface/inspector/capitalize_properties", true);
EDITOR_DEF_RST("interface/inspector/default_float_step", 0.001);
diff --git a/editor/editor_property_name_processor.cpp b/editor/editor_property_name_processor.cpp
new file mode 100644
index 0000000000..38003ab2f4
--- /dev/null
+++ b/editor/editor_property_name_processor.cpp
@@ -0,0 +1,121 @@
+/*************************************************************************/
+/* editor_property_name_processor.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "editor_property_name_processor.h"
+
+#include "editor_settings.h"
+
+EditorPropertyNameProcessor *EditorPropertyNameProcessor::singleton = nullptr;
+
+String EditorPropertyNameProcessor::_capitalize_name(const String &p_name) const {
+ String capitalized_string = p_name.capitalize();
+
+ // Fix the casing of a few strings commonly found in editor property/setting names.
+ for (Map<String, String>::Element *E = capitalize_string_remaps.front(); E; E = E->next()) {
+ capitalized_string = capitalized_string.replace(E->key(), E->value());
+ }
+
+ return capitalized_string;
+}
+
+String EditorPropertyNameProcessor::process_name(const String &p_name) const {
+ const String capitalized_string = _capitalize_name(p_name);
+ if (EDITOR_GET("interface/editor/translate_properties")) {
+ return TTRGET(capitalized_string);
+ }
+ return capitalized_string;
+}
+
+String EditorPropertyNameProcessor::make_tooltip_for_name(const String &p_name) const {
+ const String capitalized_string = _capitalize_name(p_name);
+ if (EDITOR_GET("interface/editor/translate_properties")) {
+ return capitalized_string;
+ }
+ return TTRGET(capitalized_string);
+}
+
+EditorPropertyNameProcessor::EditorPropertyNameProcessor() {
+ ERR_FAIL_COND(singleton != nullptr);
+ singleton = this;
+
+ // The following initialization is parsed in `editor/translations/extract.py` with a regex.
+ // The map name and value definition format should be kept synced with the regex.
+ capitalize_string_remaps["2d"] = "2D";
+ capitalize_string_remaps["3d"] = "3D";
+ capitalize_string_remaps["Adb"] = "ADB";
+ capitalize_string_remaps["Bptc"] = "BPTC";
+ capitalize_string_remaps["Bvh"] = "BVH";
+ capitalize_string_remaps["Csg"] = "CSG";
+ capitalize_string_remaps["Cpu"] = "CPU";
+ capitalize_string_remaps["Db"] = "dB";
+ capitalize_string_remaps["Dof"] = "DoF";
+ capitalize_string_remaps["Dpi"] = "DPI";
+ capitalize_string_remaps["Etc"] = "ETC";
+ capitalize_string_remaps["Fbx"] = "FBX";
+ capitalize_string_remaps["Fps"] = "FPS";
+ capitalize_string_remaps["Fov"] = "FOV";
+ capitalize_string_remaps["Fs"] = "FS";
+ capitalize_string_remaps["Fxaa"] = "FXAA";
+ capitalize_string_remaps["Ggx"] = "GGX";
+ capitalize_string_remaps["Gdscript"] = "GDScript";
+ capitalize_string_remaps["Gles 2"] = "GLES2";
+ capitalize_string_remaps["Gles 3"] = "GLES3";
+ capitalize_string_remaps["Gi Probe"] = "GI Probe";
+ capitalize_string_remaps["Hdr"] = "HDR";
+ capitalize_string_remaps["Hidpi"] = "hiDPI";
+ capitalize_string_remaps["Ik"] = "IK";
+ capitalize_string_remaps["Ios"] = "iOS";
+ capitalize_string_remaps["Kb"] = "KB";
+ capitalize_string_remaps["Msaa"] = "MSAA";
+ capitalize_string_remaps["Macos"] = "macOS";
+ capitalize_string_remaps["Opentype"] = "OpenType";
+ capitalize_string_remaps["Png"] = "PNG";
+ capitalize_string_remaps["Pvs"] = "PVS";
+ capitalize_string_remaps["Pvrtc"] = "PVRTC";
+ capitalize_string_remaps["S 3 Tc"] = "S3TC";
+ capitalize_string_remaps["Sdfgi"] = "SDFGI";
+ capitalize_string_remaps["Srgb"] = "sRGB";
+ capitalize_string_remaps["Ssao"] = "SSAO";
+ capitalize_string_remaps["Ssl"] = "SSL";
+ capitalize_string_remaps["Ssh"] = "SSH";
+ capitalize_string_remaps["Sdk"] = "SDK";
+ capitalize_string_remaps["Tcp"] = "TCP";
+ capitalize_string_remaps["Uv 1"] = "UV1";
+ capitalize_string_remaps["Uv 2"] = "UV2";
+ capitalize_string_remaps["Vram"] = "VRAM";
+ capitalize_string_remaps["Vsync"] = "V-Sync";
+ capitalize_string_remaps["Vector 2"] = "Vector2";
+ capitalize_string_remaps["Webrtc"] = "WebRTC";
+ capitalize_string_remaps["Websocket"] = "WebSocket";
+}
+
+EditorPropertyNameProcessor::~EditorPropertyNameProcessor() {
+ singleton = nullptr;
+}
diff --git a/editor/editor_property_name_processor.h b/editor/editor_property_name_processor.h
new file mode 100644
index 0000000000..efd7abced3
--- /dev/null
+++ b/editor/editor_property_name_processor.h
@@ -0,0 +1,58 @@
+/*************************************************************************/
+/* editor_property_name_processor.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef EDITOR_PROPERTY_NAME_PROCESSOR_H
+#define EDITOR_PROPERTY_NAME_PROCESSOR_H
+
+#include "scene/main/node.h"
+
+class EditorPropertyNameProcessor : public Node {
+ GDCLASS(EditorPropertyNameProcessor, Node);
+
+ static EditorPropertyNameProcessor *singleton;
+
+ Map<String, String> capitalize_string_remaps;
+
+ String _capitalize_name(const String &p_name) const;
+
+public:
+ static EditorPropertyNameProcessor *get_singleton() { return singleton; }
+
+ // Capitalize & localize property path segments.
+ String process_name(const String &p_name) const;
+
+ // Make tooltip string for names processed by process_name().
+ String make_tooltip_for_name(const String &p_name) const;
+
+ EditorPropertyNameProcessor();
+ ~EditorPropertyNameProcessor();
+};
+
+#endif // EDITOR_PROPERTY_NAME_PROCESSOR_H
diff --git a/editor/editor_sectioned_inspector.cpp b/editor/editor_sectioned_inspector.cpp
index 19374f826a..a44cf20771 100644
--- a/editor/editor_sectioned_inspector.cpp
+++ b/editor/editor_sectioned_inspector.cpp
@@ -30,6 +30,7 @@
#include "editor_sectioned_inspector.h"
+#include "editor/editor_property_name_processor.h"
#include "editor/editor_scale.h"
class SectionedInspectorFilter : public Object {
@@ -259,7 +260,8 @@ void SectionedInspector::update_category_list() {
if (!section_map.has(metasection)) {
TreeItem *ms = sections->create_item(parent);
section_map[metasection] = ms;
- ms->set_text(0, sectionarr[i].capitalize());
+ ms->set_text(0, EditorPropertyNameProcessor::get_singleton()->process_name(sectionarr[i]));
+ ms->set_tooltip(0, EditorPropertyNameProcessor::get_singleton()->make_tooltip_for_name(sectionarr[i]));
ms->set_metadata(0, metasection);
ms->set_selectable(0, false);
}
diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp
index c0113e281e..1ec6d4a3a6 100644
--- a/editor/editor_settings_dialog.cpp
+++ b/editor/editor_settings_dialog.cpp
@@ -37,6 +37,7 @@
#include "editor/editor_file_system.h"
#include "editor/editor_log.h"
#include "editor/editor_node.h"
+#include "editor/editor_property_name_processor.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "scene/gui/margin_container.h"
@@ -430,8 +431,9 @@ void EditorSettingsDialog::_update_shortcuts() {
} else {
section = shortcuts->create_item(root);
- String item_name = section_name.capitalize();
+ String item_name = EditorPropertyNameProcessor::get_singleton()->process_name(section_name);
section->set_text(0, item_name);
+ section->set_tooltip(0, EditorPropertyNameProcessor::get_singleton()->make_tooltip_for_name(section_name));
section->set_selectable(0, false);
section->set_selectable(1, false);
section->set_custom_bg_color(0, shortcuts->get_theme_color(SNAME("prop_subsection"), SNAME("Editor")));
diff --git a/editor/translations/extract.py b/editor/translations/extract.py
index 2594629e5c..65d1341e9e 100755
--- a/editor/translations/extract.py
+++ b/editor/translations/extract.py
@@ -2,6 +2,7 @@
import fnmatch
import os
+import re
import shutil
import subprocess
import sys
@@ -31,6 +32,15 @@ for root, dirnames, filenames in os.walk("."):
matches.sort()
+remaps = {}
+remap_re = re.compile(r'capitalize_string_remaps\["(.+)"\] = "(.+)";')
+with open("editor/editor_property_name_processor.cpp") as f:
+ for line in f:
+ m = remap_re.search(line)
+ if m:
+ remaps[m.group(1)] = m.group(2)
+
+
unique_str = []
unique_loc = {}
ctx_group = {} # Store msgctx, msg, and locations.
@@ -53,6 +63,43 @@ msgstr ""
"""
+# Regex "(?P<name>(?:[^"\\]|\\.)*)" creates a group named `name` that matches a string.
+message_patterns = {
+ re.compile(r'RTR\("(?P<message>(?:[^"\\]|\\.)*)"(?:, "(?P<context>(?:[^"\\]|\\.)*)")?\)'): False,
+ re.compile(r'TTR\("(?P<message>(?:[^"\\]|\\.)*)"(?:, "(?P<context>(?:[^"\\]|\\.)*)")?\)'): False,
+ re.compile(r'TTRC\("(?P<message>(?:[^"\\]|\\.)*)"\)'): False,
+ re.compile(
+ r'TTRN\("(?P<message>(?:[^"\\]|\\.)*)", "(?P<plural_message>(?:[^"\\]|\\.)*)",[^,)]+?(?:, "(?P<context>(?:[^"\\]|\\.)*)")?\)'
+ ): False,
+ re.compile(
+ r'RTRN\("(?P<message>(?:[^"\\]|\\.)*)", "(?P<plural_message>(?:[^"\\]|\\.)*)",[^,)]+?(?:, "(?P<context>(?:[^"\\]|\\.)*)")?\)'
+ ): False,
+ re.compile(r'_initial_set\("(?P<message>[^"]+?)",'): True,
+ re.compile(r'GLOBAL_DEF(?:_RST)?\("(?P<message>[^".]+?)",'): True,
+ re.compile(r'EDITOR_DEF(?:_RST)?\("(?P<message>[^"]+?)",'): True,
+ re.compile(r'ADD_PROPERTY\(PropertyInfo\(Variant::[A-Z]+,\s*"(?P<message>[^"]+?)",'): True,
+ re.compile(r'ADD_GROUP\("(?P<message>[^"]+?)",'): False,
+}
+
+
+# See String::camelcase_to_underscore().
+capitalize_re = re.compile(r"(?<=\D)(?=\d)|(?<=\d)(?=\D([a-z]|\d))")
+
+
+def _process_editor_string(name):
+ # See String::capitalize().
+ # fmt: off
+ capitalized = " ".join(
+ part.title()
+ for part in capitalize_re.sub("_", name).replace("_", " ").split()
+ )
+ # fmt: on
+ # See EditorStringProcessor::process_string().
+ for key, value in remaps.items():
+ capitalized = capitalized.replace(key, value)
+ return capitalized
+
+
def _write_message(msgctx, msg, msg_plural, location):
global main_po
main_po += "#: " + location + "\n"
@@ -180,11 +227,6 @@ def _extract_translator_comment(line, is_block_translator_comment):
def process_file(f, fname):
-
- global main_po, unique_str, unique_loc
-
- patterns = ['RTR("', 'TTR("', 'TTRC("', 'TTRN("', 'RTRN("']
-
l = f.readline()
lc = 1
reading_translator_comment = False
@@ -207,86 +249,58 @@ def process_file(f, fname):
if not reading_translator_comment:
translator_comment = translator_comment[:-1] # Remove extra \n at the end.
- idx = 0
- pos = 0
-
- while not reading_translator_comment and pos >= 0:
- # Loop until a pattern is found. If not, next line.
- pos = l.find(patterns[idx], pos)
- if pos == -1:
- if idx < len(patterns) - 1:
- idx += 1
- pos = 0
- continue
- pos += len(patterns[idx])
-
- # Read msg until "
- msg = ""
- while pos < len(l) and (l[pos] != '"' or l[pos - 1] == "\\"):
- msg += l[pos]
- pos += 1
-
- # Read plural.
- msg_plural = ""
- if patterns[idx] in ['TTRN("', 'RTRN("']:
- pos = l.find('"', pos + 1)
- pos += 1
- while pos < len(l) and (l[pos] != '"' or l[pos - 1] == "\\"):
- msg_plural += l[pos]
- pos += 1
-
- # Read context.
- msgctx = ""
- pos += 1
- read_ctx = False
- while pos < len(l):
- if l[pos] == ")":
- break
- elif l[pos] == '"':
- read_ctx = True
- break
- pos += 1
-
- pos += 1
- if read_ctx:
- while pos < len(l) and (l[pos] != '"' or l[pos - 1] == "\\"):
- msgctx += l[pos]
- pos += 1
-
- # File location.
- location = os.path.relpath(fname).replace("\\", "/")
- if line_nb:
- location += ":" + str(lc)
-
- # Write translator comment.
- _write_translator_comment(msgctx, msg, translator_comment)
+ if not reading_translator_comment:
+ for pattern, is_property_path in message_patterns.items():
+ for m in pattern.finditer(l):
+ location = os.path.relpath(fname).replace("\\", "/")
+ if line_nb:
+ location += ":" + str(lc)
+
+ groups = m.groupdict("")
+ msg = groups.get("message", "")
+ msg_plural = groups.get("plural_message", "")
+ msgctx = groups.get("context", "")
+
+ if is_property_path:
+ for part in msg.split("/"):
+ _add_message(_process_editor_string(part), msg_plural, msgctx, location, translator_comment)
+ else:
+ _add_message(msg, msg_plural, msgctx, location, 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)
-
l = f.readline()
lc += 1
+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)
+
+
print("Updating the editor.pot template...")
for fname in matches: