Add methods for querying loaded Translation instances

This commit is contained in:
Haoyu Qiu 2025-11-09 16:17:04 +08:00
parent b79fe2e020
commit ec860ffe4a
9 changed files with 257 additions and 82 deletions

View file

@ -32,6 +32,7 @@
#include "core/string/translation.h"
#include "core/string/translation_server.h"
#include "core/variant/typed_array.h"
struct _character_accent_pair {
const char32_t character;
@ -252,27 +253,7 @@ 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) {
if (TranslationServer::get_singleton()->compare_locales(p_locale, E->get_locale()) > 0) {
res.insert(E);
}
}
return res;
}
#ifndef DISABLE_DEPRECATED
Ref<Translation> TranslationDomain::get_translation_object(const String &p_locale) const {
Ref<Translation> res;
int best_score = 0;
@ -289,6 +270,7 @@ Ref<Translation> TranslationDomain::get_translation_object(const String &p_local
}
return res;
}
#endif
void TranslationDomain::add_translation(const Ref<Translation> &p_translation) {
ERR_FAIL_COND_MSG(p_translation.is_null(), "Invalid translation provided.");
@ -303,6 +285,69 @@ void TranslationDomain::clear() {
translations.clear();
}
const HashSet<Ref<Translation>> TranslationDomain::get_translations() const {
return translations;
}
HashSet<Ref<Translation>> TranslationDomain::find_translations(const String &p_locale, bool p_exact) const {
HashSet<Ref<Translation>> res;
if (p_exact) {
for (const Ref<Translation> &E : translations) {
if (E->get_locale() == p_locale) {
res.insert(E);
}
}
} else {
for (const Ref<Translation> &E : translations) {
if (TranslationServer::get_singleton()->compare_locales(p_locale, E->get_locale()) > 0) {
res.insert(E);
}
}
}
return res;
}
bool TranslationDomain::has_translation(const Ref<Translation> &p_translation) const {
return translations.has(p_translation);
}
bool TranslationDomain::has_translation_for_locale(const String &p_locale, bool p_exact) const {
if (p_exact) {
for (const Ref<Translation> &E : translations) {
if (E->get_locale() == p_locale) {
return true;
}
}
} else {
for (const Ref<Translation> &E : translations) {
if (TranslationServer::get_singleton()->compare_locales(p_locale, E->get_locale()) > 0) {
return true;
}
}
}
return false;
}
TypedArray<Translation> TranslationDomain::get_translations_bind() const {
TypedArray<Translation> res;
res.reserve(translations.size());
for (const Ref<Translation> &E : translations) {
res.push_back(E);
}
return res;
}
TypedArray<Translation> TranslationDomain::find_translations_bind(const String &p_locale, bool p_exact) const {
const HashSet<Ref<Translation>> &found = find_translations(p_locale, p_exact);
TypedArray<Translation> res;
res.reserve(found.size());
for (const Ref<Translation> &E : found) {
res.push_back(E);
}
return res;
}
StringName TranslationDomain::translate(const StringName &p_message, const StringName &p_context) const {
if (!enabled) {
return p_message;
@ -459,10 +504,17 @@ StringName TranslationDomain::pseudolocalize(const StringName &p_message) const
}
void TranslationDomain::_bind_methods() {
#ifndef DISABLE_DEPRECATED
ClassDB::bind_method(D_METHOD("get_translation_object", "locale"), &TranslationDomain::get_translation_object);
#endif
ClassDB::bind_method(D_METHOD("add_translation", "translation"), &TranslationDomain::add_translation);
ClassDB::bind_method(D_METHOD("remove_translation", "translation"), &TranslationDomain::remove_translation);
ClassDB::bind_method(D_METHOD("clear"), &TranslationDomain::clear);
ClassDB::bind_method(D_METHOD("get_translations"), &TranslationDomain::get_translations_bind);
ClassDB::bind_method(D_METHOD("has_translation_for_locale", "locale", "exact"), &TranslationDomain::has_translation_for_locale);
ClassDB::bind_method(D_METHOD("has_translation", "translation"), &TranslationDomain::has_translation);
ClassDB::bind_method(D_METHOD("find_translations", "locale", "exact"), &TranslationDomain::find_translations_bind);
ClassDB::bind_method(D_METHOD("translate", "message", "context"), &TranslationDomain::translate, DEFVAL(StringName()));
ClassDB::bind_method(D_METHOD("translate_plural", "message", "message_plural", "n", "context"), &TranslationDomain::translate_plural, DEFVAL(StringName()));
ClassDB::bind_method(D_METHOD("get_locale_override"), &TranslationDomain::get_locale_override);

View file

@ -71,16 +71,25 @@ 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:
// These two methods are public for easier TranslationServer bindings.
TypedArray<Translation> get_translations_bind() const;
TypedArray<Translation> find_translations_bind(const String &p_locale, bool p_exact) const;
#ifndef DISABLE_DEPRECATED
Ref<Translation> get_translation_object(const String &p_locale) const;
#endif
void add_translation(const Ref<Translation> &p_translation);
void remove_translation(const Ref<Translation> &p_translation);
void clear();
bool has_translation(const Ref<Translation> &p_translation) const;
const HashSet<Ref<Translation>> get_translations() const;
HashSet<Ref<Translation>> find_translations(const String &p_locale, bool p_exact) const;
bool has_translation_for_locale(const String &p_locale, bool p_exact) const;
StringName translate(const StringName &p_message, const StringName &p_context) const;
StringName translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context) const;

View file

@ -36,6 +36,7 @@
#include "core/os/main_loop.h"
#include "core/os/os.h"
#include "core/string/locales.h"
#include "core/variant/typed_array.h"
void TranslationServer::init_locale_info() {
// Init locale info.
@ -503,9 +504,27 @@ void TranslationServer::remove_translation(const Ref<Translation> &p_translation
main_domain->remove_translation(p_translation);
}
#ifndef DISABLE_DEPRECATED
Ref<Translation> TranslationServer::get_translation_object(const String &p_locale) {
return main_domain->get_translation_object(p_locale);
}
#endif
TypedArray<Translation> TranslationServer::get_translations() const {
return main_domain->get_translations_bind();
}
TypedArray<Translation> TranslationServer::find_translations(const String &p_locale, bool p_exact) const {
return main_domain->find_translations_bind(p_locale, p_exact);
}
bool TranslationServer::has_translation(const Ref<Translation> &p_translation) const {
return main_domain->has_translation(p_translation);
}
bool TranslationServer::has_translation_for_locale(const String &p_locale, bool p_exact) const {
return main_domain->has_translation_for_locale(p_locale, p_exact);
}
void TranslationServer::clear() {
main_domain->clear();
@ -576,21 +595,27 @@ 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()) {
if (editor_domain->has_translation_for_locale(locale)) {
if (editor_domain->has_translation_for_locale(locale, true)) {
return locale;
}
return "en";
} else {
#else
{
#endif
// Look for best matching loaded translation.
Ref<Translation> t = main_domain->get_translation_object(locale);
if (t.is_null()) {
return fallback;
}
return t->get_locale();
}
#endif
Ref<Translation> res;
int best_score = 0;
for (const Ref<Translation> &E : main_domain->get_translations()) {
int score = TranslationServer::get_singleton()->compare_locales(locale, E->get_locale());
if (score > 0 && score >= best_score) {
res = E;
best_score = score;
if (score == 10) {
return locale; // Exact match.
}
}
}
return res.is_valid() ? res->get_locale() : fallback;
}
bool TranslationServer::is_pseudolocalization_enabled() const {
@ -676,7 +701,15 @@ void TranslationServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_translation", "translation"), &TranslationServer::add_translation);
ClassDB::bind_method(D_METHOD("remove_translation", "translation"), &TranslationServer::remove_translation);
#ifndef DISABLE_DEPRECATED
ClassDB::bind_method(D_METHOD("get_translation_object", "locale"), &TranslationServer::get_translation_object);
#endif
ClassDB::bind_method(D_METHOD("get_translations"), &TranslationServer::get_translations);
ClassDB::bind_method(D_METHOD("find_translations", "locale", "exact"), &TranslationServer::find_translations);
ClassDB::bind_method(D_METHOD("has_translation_for_locale", "locale", "exact"), &TranslationServer::has_translation_for_locale);
ClassDB::bind_method(D_METHOD("has_translation", "translation"), &TranslationServer::has_translation);
ClassDB::bind_method(D_METHOD("has_domain", "domain"), &TranslationServer::has_domain);
ClassDB::bind_method(D_METHOD("get_or_add_domain", "domain"), &TranslationServer::get_or_add_domain);

View file

@ -110,7 +110,15 @@ public:
String get_locale() const;
void set_fallback_locale(const String &p_locale);
String get_fallback_locale() const;
#ifndef DISABLE_DEPRECATED
Ref<Translation> get_translation_object(const String &p_locale);
#endif
bool has_translation(const Ref<Translation> &p_translation) const;
TypedArray<Translation> get_translations() const;
TypedArray<Translation> find_translations(const String &p_locale, bool p_exact) const;
bool has_translation_for_locale(const String &p_locale, bool p_exact) const;
Vector<String> get_all_languages() const;
String get_language_name(const String &p_language) const;