2
0
Эх сурвалжийг харах

Cleanup editor translation related methods

- Unify logic for loading editor/property/doc/extractable translations.
- Replace legacy `TranslationServer` methods with translation domains for internal translations.
- Only pre-create editor/property/doc translation domains in editor builds.
- Prevent adding `null` translation.
- Fixes potential loading of duplicated editor translations.
- Add internal `has_translation_for_locale()` instead of calling `get_loaded_translations().has()`.
Haoyu Qiu 5 сар өмнө
parent
commit
3f03260a21

+ 10 - 7
core/string/translation_domain.cpp

@@ -202,7 +202,6 @@ StringName TranslationDomain::get_message_from_translations(const String &p_loca
 	int best_score = 0;
 
 	for (const Ref<Translation> &E : translations) {
-		ERR_CONTINUE(E.is_null());
 		int score = TranslationServer::get_singleton()->compare_locales(p_locale, E->get_locale());
 		if (score > 0 && score >= best_score) {
 			const StringName r = E->get_message(p_message, p_context);
@@ -225,7 +224,6 @@ StringName TranslationDomain::get_message_from_translations(const String &p_loca
 	int best_score = 0;
 
 	for (const Ref<Translation> &E : translations) {
-		ERR_CONTINUE(E.is_null());
 		int score = TranslationServer::get_singleton()->compare_locales(p_locale, E->get_locale());
 		if (score > 0 && score >= best_score) {
 			const StringName r = E->get_plural_message(p_message, p_message_plural, p_n, p_context);
@@ -246,7 +244,6 @@ StringName TranslationDomain::get_message_from_translations(const String &p_loca
 PackedStringArray TranslationDomain::get_loaded_locales() const {
 	PackedStringArray locales;
 	for (const Ref<Translation> &E : translations) {
-		ERR_CONTINUE(E.is_null());
 		const String &locale = E->get_locale();
 		if (!locales.has(locale)) {
 			locales.push_back(locale);
@@ -255,13 +252,20 @@ PackedStringArray TranslationDomain::get_loaded_locales() const {
 	return locales;
 }
 
+bool TranslationDomain::has_translation_for_locale(const String &p_locale) const {
+	for (const Ref<Translation> &E : translations) {
+		if (E->get_locale() == p_locale) {
+			return true;
+		}
+	}
+	return false;
+}
+
 // Translation objects that could potentially be used for the given locale.
 HashSet<Ref<Translation>> TranslationDomain::get_potential_translations(const String &p_locale) const {
 	HashSet<Ref<Translation>> res;
 
 	for (const Ref<Translation> &E : translations) {
-		ERR_CONTINUE(E.is_null());
-
 		if (TranslationServer::get_singleton()->compare_locales(p_locale, E->get_locale()) > 0) {
 			res.insert(E);
 		}
@@ -274,8 +278,6 @@ Ref<Translation> TranslationDomain::get_translation_object(const String &p_local
 	int best_score = 0;
 
 	for (const Ref<Translation> &E : translations) {
-		ERR_CONTINUE(E.is_null());
-
 		int score = TranslationServer::get_singleton()->compare_locales(p_locale, E->get_locale());
 		if (score > 0 && score >= best_score) {
 			res = E;
@@ -289,6 +291,7 @@ Ref<Translation> TranslationDomain::get_translation_object(const String &p_local
 }
 
 void TranslationDomain::add_translation(const Ref<Translation> &p_translation) {
+	ERR_FAIL_COND_MSG(p_translation.is_null(), "Invalid translation provided.");
 	translations.insert(p_translation);
 }
 

+ 1 - 0
core/string/translation_domain.h

@@ -71,6 +71,7 @@ public:
 	StringName get_message_from_translations(const String &p_locale, const StringName &p_message, const StringName &p_context) const;
 	StringName get_message_from_translations(const String &p_locale, const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context) const;
 	PackedStringArray get_loaded_locales() const;
+	bool has_translation_for_locale(const String &p_locale) const;
 	HashSet<Ref<Translation>> get_potential_translations(const String &p_locale) const;
 
 public:

+ 6 - 22
core/string/translation_server.cpp

@@ -470,8 +470,7 @@ void TranslationServer::setup() {
 String TranslationServer::get_tool_locale() {
 #ifdef TOOLS_ENABLED
 	if (Engine::get_singleton()->is_editor_hint() || Engine::get_singleton()->is_project_manager_hint()) {
-		const PackedStringArray &locales = editor_domain->get_loaded_locales();
-		if (locales.has(locale)) {
+		if (editor_domain->has_translation_for_locale(locale)) {
 			return locale;
 		}
 		return "en";
@@ -488,26 +487,6 @@ String TranslationServer::get_tool_locale() {
 	}
 }
 
-StringName TranslationServer::tool_translate(const StringName &p_message, const StringName &p_context) const {
-	return editor_domain->translate(p_message, p_context);
-}
-
-StringName TranslationServer::tool_translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context) const {
-	return editor_domain->translate_plural(p_message, p_message_plural, p_n, p_context);
-}
-
-StringName TranslationServer::property_translate(const StringName &p_message, const StringName &p_context) const {
-	return property_domain->translate(p_message, p_context);
-}
-
-StringName TranslationServer::doc_translate(const StringName &p_message, const StringName &p_context) const {
-	return doc_domain->translate(p_message, p_context);
-}
-
-StringName TranslationServer::doc_translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context) const {
-	return doc_domain->translate_plural(p_message, p_message_plural, p_n, p_context);
-}
-
 bool TranslationServer::is_pseudolocalization_enabled() const {
 	return main_domain->is_pseudolocalization_enabled();
 }
@@ -623,9 +602,14 @@ void TranslationServer::load_translations() {
 
 TranslationServer::TranslationServer() {
 	singleton = this;
+
 	main_domain.instantiate();
+
+#ifdef TOOLS_ENABLED
 	editor_domain = get_or_add_domain("godot.editor");
 	property_domain = get_or_add_domain("godot.properties");
 	doc_domain = get_or_add_domain("godot.documentation");
+#endif // TOOLS_ENABLED
+
 	init_locale_info();
 }

+ 7 - 5
core/string/translation_server.h

@@ -40,9 +40,11 @@ class TranslationServer : public Object {
 	String fallback;
 
 	Ref<TranslationDomain> main_domain;
+#ifdef TOOLS_ENABLED
 	Ref<TranslationDomain> editor_domain;
 	Ref<TranslationDomain> property_domain;
 	Ref<TranslationDomain> doc_domain;
+#endif // TOOLS_ENABLED
 	HashMap<StringName, Ref<TranslationDomain>> custom_domains;
 
 	mutable HashMap<String, int> locale_compare_cache;
@@ -94,8 +96,13 @@ class TranslationServer : public Object {
 public:
 	_FORCE_INLINE_ static TranslationServer *get_singleton() { return singleton; }
 
+	// Built-in domain accessors. For engine code only, user code should use `get_or_add_domain()` instead.
 	Ref<TranslationDomain> get_main_domain() const { return main_domain; }
+#ifdef TOOLS_ENABLED
 	Ref<TranslationDomain> get_editor_domain() const { return editor_domain; }
+	Ref<TranslationDomain> get_property_domain() const { return property_domain; }
+	Ref<TranslationDomain> get_doc_domain() const { return doc_domain; }
+#endif // TOOLS_ENABLED
 
 	void set_locale(const String &p_locale);
 	String get_locale() const;
@@ -133,11 +140,6 @@ public:
 	int compare_locales(const String &p_locale_a, const String &p_locale_b) const;
 
 	String get_tool_locale();
-	StringName tool_translate(const StringName &p_message, const StringName &p_context = "") const;
-	StringName tool_translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context = "") const;
-	StringName property_translate(const StringName &p_message, const StringName &p_context = "") const;
-	StringName doc_translate(const StringName &p_message, const StringName &p_context = "") const;
-	StringName doc_translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context = "") const;
 
 	bool has_domain(const StringName &p_domain) const;
 	Ref<TranslationDomain> get_or_add_domain(const StringName &p_domain);

+ 16 - 12
core/string/ustring.cpp

@@ -5944,7 +5944,7 @@ Vector<uint8_t> String::to_multibyte_char_buffer(const String &p_encoding) const
  */
 String TTR(const String &p_text, const String &p_context) {
 	if (TranslationServer::get_singleton()) {
-		return TranslationServer::get_singleton()->tool_translate(p_text, p_context);
+		return TranslationServer::get_singleton()->get_editor_domain()->translate(p_text, p_context);
 	}
 
 	return p_text;
@@ -5964,7 +5964,7 @@ String TTR(const String &p_text, const String &p_context) {
  */
 String TTRN(const String &p_text, const String &p_text_plural, int p_n, const String &p_context) {
 	if (TranslationServer::get_singleton()) {
-		return TranslationServer::get_singleton()->tool_translate_plural(p_text, p_text_plural, p_n, p_context);
+		return TranslationServer::get_singleton()->get_editor_domain()->translate_plural(p_text, p_text_plural, p_n, p_context);
 	}
 
 	// Return message based on English plural rule if translation is not possible.
@@ -5985,7 +5985,7 @@ String DTR(const String &p_text, const String &p_context) {
 	const String text = p_text.dedent().strip_edges();
 
 	if (TranslationServer::get_singleton()) {
-		return String(TranslationServer::get_singleton()->doc_translate(text, p_context)).replace("$DOCS_URL", GODOT_VERSION_DOCS_URL);
+		return String(TranslationServer::get_singleton()->get_doc_domain()->translate(text, p_context)).replace("$DOCS_URL", GODOT_VERSION_DOCS_URL);
 	}
 
 	return text.replace("$DOCS_URL", GODOT_VERSION_DOCS_URL);
@@ -6002,7 +6002,7 @@ String DTRN(const String &p_text, const String &p_text_plural, int p_n, const St
 	const String text_plural = p_text_plural.dedent().strip_edges();
 
 	if (TranslationServer::get_singleton()) {
-		return String(TranslationServer::get_singleton()->doc_translate_plural(text, text_plural, p_n, p_context)).replace("$DOCS_URL", GODOT_VERSION_DOCS_URL);
+		return String(TranslationServer::get_singleton()->get_doc_domain()->translate_plural(text, text_plural, p_n, p_context)).replace("$DOCS_URL", GODOT_VERSION_DOCS_URL);
 	}
 
 	// Return message based on English plural rule if translation is not possible.
@@ -6026,11 +6026,13 @@ String DTRN(const String &p_text, const String &p_text_plural, int p_n, const St
  */
 String RTR(const String &p_text, const String &p_context) {
 	if (TranslationServer::get_singleton()) {
-		String rtr = TranslationServer::get_singleton()->tool_translate(p_text, p_context);
-		if (rtr.is_empty() || rtr == p_text) {
-			return TranslationServer::get_singleton()->translate(p_text, p_context);
+#ifdef TOOLS_ENABLED
+		String rtr = TranslationServer::get_singleton()->get_editor_domain()->translate(p_text, p_context);
+		if (!rtr.is_empty() && rtr != p_text) {
+			return rtr;
 		}
-		return rtr;
+#endif // TOOLS_ENABLED
+		return TranslationServer::get_singleton()->translate(p_text, p_context);
 	}
 
 	return p_text;
@@ -6049,11 +6051,13 @@ String RTR(const String &p_text, const String &p_context) {
  */
 String RTRN(const String &p_text, const String &p_text_plural, int p_n, const String &p_context) {
 	if (TranslationServer::get_singleton()) {
-		String rtr = TranslationServer::get_singleton()->tool_translate_plural(p_text, p_text_plural, p_n, p_context);
-		if (rtr.is_empty() || rtr == p_text || rtr == p_text_plural) {
-			return TranslationServer::get_singleton()->translate_plural(p_text, p_text_plural, p_n, p_context);
+#ifdef TOOLS_ENABLED
+		String rtr = TranslationServer::get_singleton()->get_editor_domain()->translate_plural(p_text, p_text_plural, p_n, p_context);
+		if (!rtr.is_empty() && rtr != p_text && rtr != p_text_plural) {
+			return rtr;
 		}
-		return rtr;
+#endif // TOOLS_ENABLED
+		return TranslationServer::get_singleton()->translate_plural(p_text, p_text_plural, p_n, p_context);
 	}
 
 	// Return message based on English plural rule if translation is not possible.

+ 1 - 1
editor/doc/doc_tools.cpp

@@ -71,7 +71,7 @@ static String _get_indent(const String &p_text) {
 static String _translate_doc_string(const String &p_text) {
 	const String indent = _get_indent(p_text);
 	const String message = p_text.dedent().strip_edges();
-	const String translated = TranslationServer::get_singleton()->doc_translate(message, "");
+	const String translated = TranslationServer::get_singleton()->get_doc_domain()->translate(message, StringName());
 	// No need to restore stripped edges because they'll be stripped again later.
 	return translated.indent(indent);
 }

+ 9 - 3
editor/editor_builders.py

@@ -124,7 +124,7 @@ inline constexpr const unsigned char _{category}_translation_{name}_compressed[]
         file.write(f"""\
 #include "{target_h}"
 
-const {category.capitalize()}TranslationList _{category}_translations[] = {{
+const EditorTranslationList _{category}_translations[] = {{
 """)
 
         for x in xl_names:
@@ -137,12 +137,18 @@ const {category.capitalize()}TranslationList _{category}_translations[] = {{
 
     with methods.generated_wrapper(target_h) as file:
         file.write(f"""\
-struct {category.capitalize()}TranslationList {{
+
+#ifndef EDITOR_TRANSLATION_LIST
+#define EDITOR_TRANSLATION_LIST
+
+struct EditorTranslationList {{
 	const char* lang;
 	int comp_size;
 	int uncomp_size;
 	const unsigned char* data;
 }};
 
-extern const {category.capitalize()}TranslationList _{category}_translations[];
+#endif // EDITOR_TRANSLATION_LIST
+
+extern const EditorTranslationList _{category}_translations[];
 """)

+ 1 - 1
editor/editor_node.cpp

@@ -578,7 +578,7 @@ void EditorNode::_update_translations() {
 	if (main->is_enabled()) {
 		// Check for the exact locale.
 		// `get_potential_translations("zh_CN")` could return translations for "zh".
-		if (main->get_loaded_locales().has(main->get_locale_override())) {
+		if (main->has_translation_for_locale(main->get_locale_override())) {
 			// The set of translation resources for the current locale changed.
 			const HashSet<Ref<Translation>> translations = main->get_potential_translations(main->get_locale_override());
 			if (translations != tracked_translations) {

+ 2 - 2
editor/inspector/editor_property_name_processor.cpp

@@ -120,7 +120,7 @@ String EditorPropertyNameProcessor::process_name(const String &p_name, Style p_s
 		case STYLE_LOCALIZED: {
 			const String capitalized = _capitalize_name(p_name);
 			if (TranslationServer::get_singleton()) {
-				return TranslationServer::get_singleton()->property_translate(capitalized, _get_context(p_name, p_property, p_class));
+				return TranslationServer::get_singleton()->get_property_domain()->translate(capitalized, _get_context(p_name, p_property, p_class));
 			}
 			return capitalized;
 		} break;
@@ -130,7 +130,7 @@ String EditorPropertyNameProcessor::process_name(const String &p_name, Style p_s
 
 String EditorPropertyNameProcessor::translate_group_name(const String &p_name) const {
 	if (TranslationServer::get_singleton()) {
-		return TranslationServer::get_singleton()->property_translate(p_name);
+		return TranslationServer::get_singleton()->get_property_domain()->translate(p_name, StringName());
 	}
 	return p_name;
 }

+ 1 - 7
editor/settings/editor_settings.cpp

@@ -1327,16 +1327,10 @@ void EditorSettings::setup_language() {
 		TranslationServer::get_singleton()->set_locale(lang);
 		return; // Default, nothing to do.
 	}
-	// Load editor translation for configured/detected locale.
-	load_editor_translations(lang);
-	load_property_translations(lang);
 
-	// Load class reference translation.
+	load_editor_translations(lang);
 	load_doc_translations(lang);
 
-	// Load extractable translation for projects.
-	load_extractable_translations(lang);
-
 	TranslationServer::get_singleton()->set_locale(lang);
 }
 

+ 23 - 101
editor/translations/editor_translation.cpp

@@ -42,26 +42,20 @@
 Vector<String> get_editor_locales() {
 	Vector<String> locales;
 
-	const EditorTranslationList *etl = _editor_translations;
-	while (etl->data) {
+	for (const EditorTranslationList *etl = _editor_translations; etl->data; etl++) {
 		const String &locale = etl->lang;
 		locales.push_back(locale);
-
-		etl++;
 	}
 
 	return locales;
 }
 
-void load_editor_translations(const String &p_locale) {
-	const Ref<TranslationDomain> domain = TranslationServer::get_singleton()->get_or_add_domain("godot.editor");
-
-	const EditorTranslationList *etl = _editor_translations;
-	while (etl->data) {
+static void _load(const Ref<TranslationDomain> p_domain, const String &p_locale, const EditorTranslationList *p_etl) {
+	for (const EditorTranslationList *etl = p_etl; etl->data; etl++) {
 		if (etl->lang == p_locale) {
-			Vector<uint8_t> data;
-			data.resize(etl->uncomp_size);
-			const int64_t ret = Compression::decompress(data.ptrw(), etl->uncomp_size, etl->data, etl->comp_size, Compression::MODE_DEFLATE);
+			LocalVector<uint8_t> data;
+			data.resize_uninitialized(etl->uncomp_size);
+			const int64_t ret = Compression::decompress(data.ptr(), etl->uncomp_size, etl->data, etl->comp_size, Compression::MODE_DEFLATE);
 			ERR_FAIL_COND_MSG(ret == -1, "Compressed file is corrupt.");
 
 			Ref<FileAccessMemory> fa;
@@ -69,115 +63,45 @@ void load_editor_translations(const String &p_locale) {
 			fa->open_custom(data.ptr(), data.size());
 
 			Ref<Translation> tr = TranslationLoaderPO::load_translation(fa);
-
 			if (tr.is_valid()) {
 				tr->set_locale(etl->lang);
-				domain->add_translation(tr);
+				p_domain->add_translation(tr);
 				break;
 			}
 		}
-
-		etl++;
 	}
 }
 
-void load_property_translations(const String &p_locale) {
-	const Ref<TranslationDomain> domain = TranslationServer::get_singleton()->get_or_add_domain("godot.properties");
-
-	const PropertyTranslationList *etl = _property_translations;
-	while (etl->data) {
-		if (etl->lang == p_locale) {
-			Vector<uint8_t> data;
-			data.resize(etl->uncomp_size);
-			const int64_t ret = Compression::decompress(data.ptrw(), etl->uncomp_size, etl->data, etl->comp_size, Compression::MODE_DEFLATE);
-			ERR_FAIL_COND_MSG(ret == -1, "Compressed file is corrupt.");
-
-			Ref<FileAccessMemory> fa;
-			fa.instantiate();
-			fa->open_custom(data.ptr(), data.size());
-
-			Ref<Translation> tr = TranslationLoaderPO::load_translation(fa);
+void load_editor_translations(const String &p_locale) {
+	Ref<TranslationDomain> domain;
 
-			if (tr.is_valid()) {
-				tr->set_locale(etl->lang);
-				domain->add_translation(tr);
-				break;
-			}
-		}
+	domain = TranslationServer::get_singleton()->get_editor_domain();
+	domain->clear();
+	_load(domain, p_locale, _editor_translations);
+	_load(domain, p_locale, _extractable_translations);
 
-		etl++;
-	}
+	domain = TranslationServer::get_singleton()->get_property_domain();
+	domain->clear();
+	_load(domain, p_locale, _property_translations);
 }
 
 void load_doc_translations(const String &p_locale) {
-	const Ref<TranslationDomain> domain = TranslationServer::get_singleton()->get_or_add_domain("godot.documentation");
-
-	const DocTranslationList *dtl = _doc_translations;
-	while (dtl->data) {
-		if (dtl->lang == p_locale) {
-			Vector<uint8_t> data;
-			data.resize(dtl->uncomp_size);
-			const int64_t ret = Compression::decompress(data.ptrw(), dtl->uncomp_size, dtl->data, dtl->comp_size, Compression::MODE_DEFLATE);
-			ERR_FAIL_COND_MSG(ret == -1, "Compressed file is corrupt.");
-
-			Ref<FileAccessMemory> fa;
-			fa.instantiate();
-			fa->open_custom(data.ptr(), data.size());
-
-			Ref<Translation> tr = TranslationLoaderPO::load_translation(fa);
-
-			if (tr.is_valid()) {
-				tr->set_locale(dtl->lang);
-				domain->add_translation(tr);
-				break;
-			}
-		}
-
-		dtl++;
-	}
-}
-
-void load_extractable_translations(const String &p_locale) {
-	const Ref<TranslationDomain> domain = TranslationServer::get_singleton()->get_or_add_domain("godot.editor");
-
-	const ExtractableTranslationList *etl = _extractable_translations;
-	while (etl->data) {
-		if (etl->lang == p_locale) {
-			Vector<uint8_t> data;
-			data.resize(etl->uncomp_size);
-			const int64_t ret = Compression::decompress(data.ptrw(), etl->uncomp_size, etl->data, etl->comp_size, Compression::MODE_DEFLATE);
-			ERR_FAIL_COND_MSG(ret == -1, "Compressed file is corrupt.");
-
-			Ref<FileAccessMemory> fa;
-			fa.instantiate();
-			fa->open_custom(data.ptr(), data.size());
-
-			Ref<Translation> tr = TranslationLoaderPO::load_translation(fa);
-
-			if (tr.is_valid()) {
-				tr->set_locale(etl->lang);
-				domain->add_translation(tr);
-				break;
-			}
-		}
-
-		etl++;
-	}
+	const Ref<TranslationDomain> domain = TranslationServer::get_singleton()->get_doc_domain();
+	domain->clear();
+	_load(domain, p_locale, _doc_translations);
 }
 
 Vector<Vector<String>> get_extractable_message_list() {
-	const ExtractableTranslationList *etl = _extractable_translations;
 	Vector<Vector<String>> list;
 
-	while (etl->data) {
+	for (const EditorTranslationList *etl = _extractable_translations; etl->data; etl++) {
 		if (strcmp(etl->lang, "source")) {
-			etl++;
 			continue;
 		}
 
-		Vector<uint8_t> data;
-		data.resize(etl->uncomp_size);
-		const int64_t ret = Compression::decompress(data.ptrw(), etl->uncomp_size, etl->data, etl->comp_size, Compression::MODE_DEFLATE);
+		LocalVector<uint8_t> data;
+		data.resize_uninitialized(etl->uncomp_size);
+		const int64_t ret = Compression::decompress(data.ptr(), etl->uncomp_size, etl->data, etl->comp_size, Compression::MODE_DEFLATE);
 		ERR_FAIL_COND_V_MSG(ret == -1, list, "Compressed file is corrupt.");
 
 		Ref<FileAccessMemory> fa;
@@ -322,8 +246,6 @@ Vector<Vector<String>> get_extractable_message_list() {
 				line++;
 			}
 		}
-
-		etl++;
 	}
 
 	return list;

+ 0 - 2
editor/translations/editor_translation.h

@@ -35,7 +35,5 @@
 
 Vector<String> get_editor_locales();
 void load_editor_translations(const String &p_locale);
-void load_property_translations(const String &p_locale);
 void load_doc_translations(const String &p_locale);
-void load_extractable_translations(const String &p_locale);
 Vector<Vector<String>> get_extractable_message_list();