Skip to content

Commit 68d494e

Browse files
committed
Add translation domain
1 parent 48403b5 commit 68d494e

File tree

7 files changed

+379
-116
lines changed

7 files changed

+379
-116
lines changed

core/register_core_types.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ void register_core_types() {
233233

234234
GDREGISTER_CLASS(MainLoop);
235235
GDREGISTER_CLASS(Translation);
236+
GDREGISTER_CLASS(TranslationDomain);
236237
GDREGISTER_CLASS(OptimizedTranslation);
237238
GDREGISTER_CLASS(UndoRedo);
238239
GDREGISTER_CLASS(TriangleMesh);

core/string/translation_domain.cpp

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/**************************************************************************/
2+
/* translation_domain.cpp */
3+
/**************************************************************************/
4+
/* This file is part of: */
5+
/* GODOT ENGINE */
6+
/* https://godotengine.org */
7+
/**************************************************************************/
8+
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9+
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10+
/* */
11+
/* Permission is hereby granted, free of charge, to any person obtaining */
12+
/* a copy of this software and associated documentation files (the */
13+
/* "Software"), to deal in the Software without restriction, including */
14+
/* without limitation the rights to use, copy, modify, merge, publish, */
15+
/* distribute, sublicense, and/or sell copies of the Software, and to */
16+
/* permit persons to whom the Software is furnished to do so, subject to */
17+
/* the following conditions: */
18+
/* */
19+
/* The above copyright notice and this permission notice shall be */
20+
/* included in all copies or substantial portions of the Software. */
21+
/* */
22+
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23+
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24+
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25+
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26+
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27+
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28+
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29+
/**************************************************************************/
30+
31+
#include "translation_domain.h"
32+
33+
#include "core/string/translation.h"
34+
#include "core/string/translation_server.h"
35+
36+
StringName TranslationDomain::get_message_from_translations(const String &p_locale, const StringName &p_message, const StringName &p_context) const {
37+
StringName res;
38+
int best_score = 0;
39+
40+
for (const Ref<Translation> &E : translations) {
41+
ERR_CONTINUE(E.is_null());
42+
int score = TranslationServer::get_singleton()->compare_locales(p_locale, E->get_locale());
43+
if (score > 0 && score >= best_score) {
44+
const StringName r = E->get_message(p_message, p_context);
45+
if (!r) {
46+
continue;
47+
}
48+
res = r;
49+
best_score = score;
50+
if (score == 10) {
51+
break; // Exact match, skip the rest.
52+
}
53+
}
54+
}
55+
56+
return res;
57+
}
58+
59+
StringName TranslationDomain::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 {
60+
StringName res;
61+
int best_score = 0;
62+
63+
for (const Ref<Translation> &E : translations) {
64+
ERR_CONTINUE(E.is_null());
65+
int score = TranslationServer::get_singleton()->compare_locales(p_locale, E->get_locale());
66+
if (score > 0 && score >= best_score) {
67+
const StringName r = E->get_plural_message(p_message, p_message_plural, p_n, p_context);
68+
if (!r) {
69+
continue;
70+
}
71+
res = r;
72+
best_score = score;
73+
if (score == 10) {
74+
break; // Exact match, skip the rest.
75+
}
76+
}
77+
}
78+
79+
return res;
80+
}
81+
82+
PackedStringArray TranslationDomain::get_loaded_locales() const {
83+
PackedStringArray locales;
84+
for (const Ref<Translation> &E : translations) {
85+
ERR_CONTINUE(E.is_null());
86+
locales.push_back(E->get_locale());
87+
}
88+
return locales;
89+
}
90+
91+
Ref<Translation> TranslationDomain::get_translation_object(const String &p_locale) const {
92+
Ref<Translation> res;
93+
int best_score = 0;
94+
95+
for (const Ref<Translation> &E : translations) {
96+
ERR_CONTINUE(E.is_null());
97+
98+
int score = TranslationServer::get_singleton()->compare_locales(p_locale, E->get_locale());
99+
if (score > 0 && score >= best_score) {
100+
res = E;
101+
best_score = score;
102+
if (score == 10) {
103+
break; // Exact match, skip the rest.
104+
}
105+
}
106+
}
107+
return res;
108+
}
109+
110+
void TranslationDomain::add_translation(const Ref<Translation> &p_translation) {
111+
translations.insert(p_translation);
112+
}
113+
114+
void TranslationDomain::remove_translation(const Ref<Translation> &p_translation) {
115+
translations.erase(p_translation);
116+
}
117+
118+
void TranslationDomain::clear() {
119+
translations.clear();
120+
}
121+
122+
StringName TranslationDomain::translate(const StringName &p_message, const StringName &p_context) const {
123+
const String &locale = TranslationServer::get_singleton()->get_locale();
124+
StringName res = get_message_from_translations(locale, p_message, p_context);
125+
126+
const String &fallback = TranslationServer::get_singleton()->get_fallback_locale();
127+
if (!res && fallback.length() >= 2) {
128+
res = get_message_from_translations(fallback, p_message, p_context);
129+
}
130+
131+
if (!res) {
132+
return p_message;
133+
}
134+
return res;
135+
}
136+
137+
StringName TranslationDomain::translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context) const {
138+
const String &locale = TranslationServer::get_singleton()->get_locale();
139+
StringName res = get_message_from_translations(locale, p_message, p_message_plural, p_n, p_context);
140+
141+
const String &fallback = TranslationServer::get_singleton()->get_fallback_locale();
142+
if (!res && fallback.length() >= 2) {
143+
res = get_message_from_translations(fallback, p_message, p_message_plural, p_n, p_context);
144+
}
145+
146+
if (!res) {
147+
if (p_n == 1) {
148+
return p_message;
149+
}
150+
return p_message_plural;
151+
}
152+
return res;
153+
}
154+
155+
void TranslationDomain::_bind_methods() {
156+
ClassDB::bind_method(D_METHOD("get_translation_object", "locale"), &TranslationDomain::get_translation_object);
157+
ClassDB::bind_method(D_METHOD("add_translation", "translation"), &TranslationDomain::add_translation);
158+
ClassDB::bind_method(D_METHOD("remove_translation", "translation"), &TranslationDomain::remove_translation);
159+
ClassDB::bind_method(D_METHOD("clear"), &TranslationDomain::clear);
160+
ClassDB::bind_method(D_METHOD("translate", "message", "context"), &TranslationDomain::translate, DEFVAL(StringName()));
161+
ClassDB::bind_method(D_METHOD("translate_plural", "message", "message_plural", "n", "context"), &TranslationDomain::translate_plural, DEFVAL(StringName()));
162+
}
163+
164+
TranslationDomain::TranslationDomain() {
165+
}

core/string/translation_domain.h

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**************************************************************************/
2+
/* translation_domain.h */
3+
/**************************************************************************/
4+
/* This file is part of: */
5+
/* GODOT ENGINE */
6+
/* https://godotengine.org */
7+
/**************************************************************************/
8+
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9+
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10+
/* */
11+
/* Permission is hereby granted, free of charge, to any person obtaining */
12+
/* a copy of this software and associated documentation files (the */
13+
/* "Software"), to deal in the Software without restriction, including */
14+
/* without limitation the rights to use, copy, modify, merge, publish, */
15+
/* distribute, sublicense, and/or sell copies of the Software, and to */
16+
/* permit persons to whom the Software is furnished to do so, subject to */
17+
/* the following conditions: */
18+
/* */
19+
/* The above copyright notice and this permission notice shall be */
20+
/* included in all copies or substantial portions of the Software. */
21+
/* */
22+
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23+
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24+
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25+
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26+
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27+
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28+
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29+
/**************************************************************************/
30+
31+
#ifndef TRANSLATION_DOMAIN_H
32+
#define TRANSLATION_DOMAIN_H
33+
34+
#include "core/object/ref_counted.h"
35+
36+
class Translation;
37+
38+
class TranslationDomain : public RefCounted {
39+
GDCLASS(TranslationDomain, RefCounted);
40+
41+
HashSet<Ref<Translation>> translations;
42+
43+
protected:
44+
static void _bind_methods();
45+
46+
public:
47+
// Methods in this section are not intended for scripting.
48+
StringName get_message_from_translations(const String &p_locale, const StringName &p_message, const StringName &p_context) const;
49+
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;
50+
PackedStringArray get_loaded_locales() const;
51+
52+
public:
53+
Ref<Translation> get_translation_object(const String &p_locale) const;
54+
55+
void add_translation(const Ref<Translation> &p_translation);
56+
void remove_translation(const Ref<Translation> &p_translation);
57+
void clear();
58+
59+
StringName translate(const StringName &p_message, const StringName &p_context) const;
60+
StringName translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context) const;
61+
62+
TranslationDomain();
63+
};
64+
65+
#endif // TRANSLATION_DOMAIN_H

0 commit comments

Comments
 (0)