Move localized number formatting methods to TranslationServer

Co-Authored-By: Pāvels Nadtočajevs <7645683+bruvzg@users.noreply.github.com>
This commit is contained in:
Haoyu Qiu 2025-10-27 21:48:09 +08:00
parent 6fd949a6dc
commit 72d437c030
27 changed files with 348 additions and 394 deletions

View file

@ -1241,3 +1241,32 @@ static const char *plural_rules[][2] = {
{ "cy", "nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n==3 ? 3 : n==6 ? 4 : 5);" }, { "cy", "nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n==3 ? 3 : n==6 ? 4 : 5);" },
{ nullptr, nullptr }, { nullptr, nullptr },
}; };
static const struct NumSystemData {
const char *locales;
const char32_t *digits;
const char32_t *percent_sign;
const char32_t *exp_l;
const char32_t *exp_u;
} num_system_data[] = {
// Eastern Arabic numerals.
{ "ar ar_AE ar_BH ar_DJ ar_EG ar_ER ar_IL ar_IQ ar_JO ar_KM ar_KW ar_LB ar_MR ar_OM ar_PS ar_QA ar_SA ar_SD ar_SO ar_SS ar_SY ar_TD ar_YE ckb ckb_IQ ckb_IR sd sd_PK sd_Arab sd_Arab_PK", U"٠١٢٣٤٥٦٧٨٩٫", U"٪", U"اس", U"اس" },
// Persian and Urdu numerals.
{ "fa fa_AF fa_IR ks ks_IN ks_Arab ks_Arab_IN lrc lrc_IQ lrc_IR mzn mzn_IR pa_PK pa_Arab pa_Arab_PK ps ps_AF ps_PK ur_IN uz_AF uz_Arab uz_Arab_AF", U"۰۱۲۳۴۵۶۷۸۹٫", U"٪", U"اس", U"اس" },
// Bengali numerals.
{ "as as_IN bn bn_BD bn_IN mni mni_IN mni_Beng mni_Beng_IN", U"০১২৩৪৫৬৭৮৯.", U"%", U"e", U"E" },
// Devanagari numerals.
{ "mr mr_IN ne ne_IN ne_NP sa sa_IN", U"०१२३४५६७८९.", U"%", U"e", U"E" },
// Dzongkha numerals.
{ "dz dz_BT", U"༠༡༢༣༤༥༦༧༨༩.", U"%", U"e", U"E" },
// Santali numerals.
{ "sat sat_IN sat_Olck sat_Olck_IN", U"᱐᱑᱒᱓᱔᱕᱖᱗᱘᱙.", U"%", U"e", U"E" },
// Burmese numerals.
{ "my my_MM", U"၀၁၂၃၄၅၆၇၈၉.", U"%", U"e", U"E" },
// Chakma numerals.
{ "ccp ccp_BD ccp_IN", U"𑄶𑄷𑄸𑄹𑄺𑄻𑄼𑄽𑄾𑄿.", U"%", U"e", U"E" },
// Adlam numerals.
{ "ff ff_Adlm_BF ff_Adlm_CM ff_Adlm_GH ff_Adlm_GM ff_Adlm_GN ff_Adlm_GW ff_Adlm_LR ff_Adlm_MR ff_Adlm_NE ff_Adlm_NG ff_Adlm_SL ff_Adlm_SN", U"𞥐𞥑𞥒𞥓𞥔𞥕𞥖𞥗𞥘𞥙.", U"%", U"𞤉", U"𞤉" },
// End sentinel.
{ nullptr, nullptr, nullptr, nullptr, nullptr }
};

View file

@ -117,6 +117,26 @@ void TranslationServer::init_locale_info() {
} }
idx++; idx++;
} }
// Init number systems.
num_system_map.clear();
idx = 0;
while (num_system_data[idx].locales != nullptr) {
const NumSystemData &nsd = num_system_data[idx];
// These fields must not be empty.
DEV_ASSERT(nsd.percent_sign && nsd.percent_sign[0] != '\0');
DEV_ASSERT(nsd.digits && nsd.digits[0] != '\0');
DEV_ASSERT(nsd.exp_l && nsd.exp_l[0] != '\0');
DEV_ASSERT(nsd.exp_u && nsd.exp_u[0] != '\0');
DEV_ASSERT(strlen(nsd.digits) == 11);
const Vector<String> locales = String(nsd.locales).split(" ");
for (const String &l : locales) {
num_system_map[l] = idx;
}
idx++;
}
} }
TranslationServer::Locale::operator String() const { TranslationServer::Locale::operator String() const {
@ -219,6 +239,66 @@ TranslationServer::Locale::Locale(const TranslationServer &p_server, const Strin
} }
} }
String TranslationServer::format_number(const String &p_string, const String &p_locale) const {
ERR_FAIL_COND_V(p_locale.is_empty(), p_string);
if (!num_system_map.has(p_locale)) {
return p_string;
}
int index = num_system_map[p_locale];
const NumSystemData &nsd = num_system_data[index];
String res = p_string;
res = res.replace("e", nsd.exp_l);
res = res.replace("E", nsd.exp_u);
char32_t *data = res.ptrw();
for (int j = 0; j < res.length(); j++) {
if (data[j] >= 0x30 && data[j] <= 0x39) {
data[j] = nsd.digits[data[j] - 0x30];
} else if (data[j] == '.' || data[j] == ',') {
data[j] = nsd.digits[10];
}
}
return res;
}
String TranslationServer::parse_number(const String &p_string, const String &p_locale) const {
ERR_FAIL_COND_V(p_locale.is_empty(), p_string);
if (!num_system_map.has(p_locale)) {
return p_string;
}
int index = num_system_map[p_locale];
const NumSystemData &nsd = num_system_data[index];
String res = p_string;
res = res.replace(nsd.exp_l, "e");
res = res.replace(nsd.exp_u, "E");
char32_t *data = res.ptrw();
for (int j = 0; j < res.length(); j++) {
if (data[j] == nsd.digits[10]) {
data[j] = '.';
} else {
for (int k = 0; k < 10; k++) {
if (data[j] == nsd.digits[k]) {
data[j] = 0x30 + k;
}
}
}
}
return res;
}
String TranslationServer::get_percent_sign(const String &p_locale) const {
ERR_FAIL_COND_V(p_locale.is_empty(), "%");
if (!num_system_map.has(p_locale)) {
return "%";
}
int index = num_system_map[p_locale];
return num_system_data[index].percent_sign;
}
String TranslationServer::standardize_locale(const String &p_locale, bool p_add_defaults) const { String TranslationServer::standardize_locale(const String &p_locale, bool p_add_defaults) const {
return Locale(*this, p_locale, p_add_defaults).operator String(); return Locale(*this, p_locale, p_add_defaults).operator String();
} }
@ -604,6 +684,10 @@ void TranslationServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_loaded_locales"), &TranslationServer::get_loaded_locales); ClassDB::bind_method(D_METHOD("get_loaded_locales"), &TranslationServer::get_loaded_locales);
ClassDB::bind_method(D_METHOD("format_number", "number", "locale"), &TranslationServer::format_number);
ClassDB::bind_method(D_METHOD("get_percent_sign", "locale"), &TranslationServer::get_percent_sign);
ClassDB::bind_method(D_METHOD("parse_number", "number", "locale"), &TranslationServer::parse_number);
ClassDB::bind_method(D_METHOD("is_pseudolocalization_enabled"), &TranslationServer::is_pseudolocalization_enabled); ClassDB::bind_method(D_METHOD("is_pseudolocalization_enabled"), &TranslationServer::is_pseudolocalization_enabled);
ClassDB::bind_method(D_METHOD("set_pseudolocalization_enabled", "enabled"), &TranslationServer::set_pseudolocalization_enabled); ClassDB::bind_method(D_METHOD("set_pseudolocalization_enabled", "enabled"), &TranslationServer::set_pseudolocalization_enabled);
ClassDB::bind_method(D_METHOD("reload_pseudolocalization"), &TranslationServer::reload_pseudolocalization); ClassDB::bind_method(D_METHOD("reload_pseudolocalization"), &TranslationServer::reload_pseudolocalization);

View file

@ -91,6 +91,7 @@ class TranslationServer : public Object {
static inline HashMap<String, String> country_rename_map; static inline HashMap<String, String> country_rename_map;
static inline HashMap<String, String> variant_map; static inline HashMap<String, String> variant_map;
static inline HashMap<String, String> plural_rules_map; static inline HashMap<String, String> plural_rules_map;
static inline HashMap<String, int> num_system_map;
void init_locale_info(); void init_locale_info();
@ -137,6 +138,10 @@ public:
void set_pseudolocalization_enabled(bool p_enabled); void set_pseudolocalization_enabled(bool p_enabled);
void reload_pseudolocalization(); void reload_pseudolocalization();
String format_number(const String &p_string, const String &p_locale) const;
String parse_number(const String &p_string, const String &p_locale) const;
String get_percent_sign(const String &p_locale) const;
String standardize_locale(const String &p_locale, bool p_add_defaults = false) const; String standardize_locale(const String &p_locale, bool p_add_defaults = false) const;
int compare_locales(const String &p_locale_a, const String &p_locale_b) const; int compare_locales(const String &p_locale_a, const String &p_locale_b) const;

View file

@ -1075,13 +1075,13 @@
Returns the dictionary of the supported OpenType variation coordinates. Returns the dictionary of the supported OpenType variation coordinates.
</description> </description>
</method> </method>
<method name="format_number" qualifiers="const"> <method name="format_number" qualifiers="const" deprecated="Use [method TranslationServer.format_number] instead.">
<return type="String" /> <return type="String" />
<param index="0" name="number" type="String" /> <param index="0" name="number" type="String" />
<param index="1" name="language" type="String" default="&quot;&quot;" /> <param index="1" name="language" type="String" default="&quot;&quot;" />
<description> <description>
Converts a number from the Western Arabic (0..9) to the numeral systems used in [param language]. Converts a number from Western Arabic (0..9) to the numeral system used in the given [param language].
If [param language] is omitted, the active locale will be used. If [param language] is an empty string, the active locale will be used.
</description> </description>
</method> </method>
<method name="free_rid"> <method name="free_rid">
@ -1197,12 +1197,13 @@
Converts readable feature, variation, script, or language name to OpenType tag. Converts readable feature, variation, script, or language name to OpenType tag.
</description> </description>
</method> </method>
<method name="parse_number" qualifiers="const"> <method name="parse_number" qualifiers="const" deprecated="Use [method TranslationServer.parse_number] instead.">
<return type="String" /> <return type="String" />
<param index="0" name="number" type="String" /> <param index="0" name="number" type="String" />
<param index="1" name="language" type="String" default="&quot;&quot;" /> <param index="1" name="language" type="String" default="&quot;&quot;" />
<description> <description>
Converts [param number] from the numeral systems used in [param language] to Western Arabic (0..9). Converts [param number] from the numeral system used in the given [param language] to Western Arabic (0..9).
If [param language] is an empty string, the active locale will be used.
</description> </description>
</method> </method>
<method name="parse_structured_text" qualifiers="const"> <method name="parse_structured_text" qualifiers="const">
@ -1214,11 +1215,12 @@
Default implementation of the BiDi algorithm override function. Default implementation of the BiDi algorithm override function.
</description> </description>
</method> </method>
<method name="percent_sign" qualifiers="const"> <method name="percent_sign" qualifiers="const" deprecated="Use [method TranslationServer.get_percent_sign] instead.">
<return type="String" /> <return type="String" />
<param index="0" name="language" type="String" default="&quot;&quot;" /> <param index="0" name="language" type="String" default="&quot;&quot;" />
<description> <description>
Returns percent sign used in the [param language]. Returns the percent sign used in the given [param language].
If [param language] is an empty string, the active locale will be used.
</description> </description>
</method> </method>
<method name="save_support_data" qualifiers="const"> <method name="save_support_data" qualifiers="const">

View file

@ -1054,12 +1054,13 @@
Returns the dictionary of the supported OpenType variation coordinates. Returns the dictionary of the supported OpenType variation coordinates.
</description> </description>
</method> </method>
<method name="_format_number" qualifiers="virtual const"> <method name="_format_number" qualifiers="virtual const" deprecated="Use [method TranslationServer.format_number] instead.">
<return type="String" /> <return type="String" />
<param index="0" name="number" type="String" /> <param index="0" name="number" type="String" />
<param index="1" name="language" type="String" /> <param index="1" name="language" type="String" />
<description> <description>
Converts a number from the Western Arabic (0..9) to the numeral systems used in [param language]. Converts a number from Western Arabic (0..9) to the numeral system used in the given [param language].
If [param language] is an empty string, the active locale will be used.
</description> </description>
</method> </method>
<method name="_free_rid" qualifiers="virtual required"> <method name="_free_rid" qualifiers="virtual required">
@ -1163,12 +1164,13 @@
Converts readable feature, variation, script, or language name to OpenType tag. Converts readable feature, variation, script, or language name to OpenType tag.
</description> </description>
</method> </method>
<method name="_parse_number" qualifiers="virtual const"> <method name="_parse_number" qualifiers="virtual const" deprecated="Use [method TranslationServer.parse_number] instead.">
<return type="String" /> <return type="String" />
<param index="0" name="number" type="String" /> <param index="0" name="number" type="String" />
<param index="1" name="language" type="String" /> <param index="1" name="language" type="String" />
<description> <description>
Converts [param number] from the numeral systems used in [param language] to Western Arabic (0..9). Converts [param number] from the numeral system used in the given [param language] to Western Arabic (0..9).
If [param language] is an empty string, the active locale will be used.
</description> </description>
</method> </method>
<method name="_parse_structured_text" qualifiers="virtual const"> <method name="_parse_structured_text" qualifiers="virtual const">
@ -1180,11 +1182,11 @@
Default implementation of the BiDi algorithm override function. Default implementation of the BiDi algorithm override function.
</description> </description>
</method> </method>
<method name="_percent_sign" qualifiers="virtual const"> <method name="_percent_sign" qualifiers="virtual const" deprecated="Use [method TranslationServer.get_percent_sign] instead.">
<return type="String" /> <return type="String" />
<param index="0" name="language" type="String" /> <param index="0" name="language" type="String" />
<description> <description>
Returns percent sign used in the [param language]. Returns percent sign used in the given [param language].
</description> </description>
</method> </method>
<method name="_reference_oversampling_level" qualifiers="virtual"> <method name="_reference_oversampling_level" qualifiers="virtual">

View file

@ -33,6 +33,14 @@
Compares two locales and returns a similarity score between [code]0[/code] (no match) and [code]10[/code] (full match). Compares two locales and returns a similarity score between [code]0[/code] (no match) and [code]10[/code] (full match).
</description> </description>
</method> </method>
<method name="format_number" qualifiers="const">
<return type="String" />
<param index="0" name="number" type="String" />
<param index="1" name="locale" type="String" />
<description>
Converts a number from Western Arabic (0..9) to the numeral system used in the given [param locale].
</description>
</method>
<method name="get_all_countries" qualifiers="const"> <method name="get_all_countries" qualifiers="const">
<return type="PackedStringArray" /> <return type="PackedStringArray" />
<description> <description>
@ -92,6 +100,13 @@
Returns the translation domain with the specified name. An empty translation domain will be created and added if it does not exist. Returns the translation domain with the specified name. An empty translation domain will be created and added if it does not exist.
</description> </description>
</method> </method>
<method name="get_percent_sign" qualifiers="const">
<return type="String" />
<param index="0" name="locale" type="String" />
<description>
Returns the percent sign used in the given [param locale].
</description>
</method>
<method name="get_plural_rules" qualifiers="const"> <method name="get_plural_rules" qualifiers="const">
<return type="String" /> <return type="String" />
<param index="0" name="locale" type="String" /> <param index="0" name="locale" type="String" />
@ -127,6 +142,14 @@
Returns [code]true[/code] if a translation domain with the specified name exists. Returns [code]true[/code] if a translation domain with the specified name exists.
</description> </description>
</method> </method>
<method name="parse_number" qualifiers="const">
<return type="String" />
<param index="0" name="number" type="String" />
<param index="1" name="locale" type="String" />
<description>
Converts [param number] from the numeral system used in the given [param locale] to Western Arabic (0..9).
</description>
</method>
<method name="pseudolocalize" qualifiers="const"> <method name="pseudolocalize" qualifiers="const">
<return type="StringName" /> <return type="StringName" />
<param index="0" name="message" type="StringName" /> <param index="0" name="message" type="StringName" />

View file

@ -30,6 +30,7 @@
#include "animation_bezier_editor.h" #include "animation_bezier_editor.h"
#include "core/string/translation_server.h"
#include "editor/animation/animation_player_editor_plugin.h" #include "editor/animation/animation_player_editor_plugin.h"
#include "editor/editor_node.h" #include "editor/editor_node.h"
#include "editor/editor_string_names.h" #include "editor/editor_string_names.h"
@ -303,6 +304,8 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
const int h_separation = get_theme_constant(SNAME("h_separation"), SNAME("AnimationBezierTrackEdit")); const int h_separation = get_theme_constant(SNAME("h_separation"), SNAME("AnimationBezierTrackEdit"));
const int v_separation = get_theme_constant(SNAME("h_separation"), SNAME("AnimationBezierTrackEdit")); const int v_separation = get_theme_constant(SNAME("h_separation"), SNAME("AnimationBezierTrackEdit"));
const String &lang = _get_locale();
if (has_focus(true)) { if (has_focus(true)) {
draw_rect(Rect2(Point2(), get_size()), focus_color, false, Math::round(EDSCALE)); draw_rect(Rect2(Point2(), get_size()), focus_color, false, Math::round(EDSCALE));
} }
@ -577,7 +580,9 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
draw_line(Point2(limit, i), Point2(right_limit, i), lc, Math::round(EDSCALE)); draw_line(Point2(limit, i), Point2(right_limit, i), lc, Math::round(EDSCALE));
Color c = color; Color c = color;
c.a *= 0.5; c.a *= 0.5;
draw_string(font, Point2(limit + 8, i - 2), TS->format_number(rtos(Math::snapped((iv + 1) * scale, step))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, c);
const String &formatted = TranslationServer::get_singleton()->format_number(rtos(Math::snapped((iv + 1) * scale, step)), lang);
draw_string(font, Point2(limit + 8, i - 2), formatted, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, c);
} }
first = false; first = false;
@ -716,8 +721,12 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
ep.point_rect.size = bezier_icon->get_size(); ep.point_rect.size = bezier_icon->get_size();
if (is_selected) { if (is_selected) {
draw_texture(selected_icon, ep.point_rect.position); draw_texture(selected_icon, ep.point_rect.position);
draw_string(font, ep.point_rect.position + Vector2(8, -font->get_height(font_size) - 8), TTR("Time:") + " " + TS->format_number(rtos(Math::snapped(offset, 0.0001))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, accent);
draw_string(font, ep.point_rect.position + Vector2(8, -8), TTR("Value:") + " " + TS->format_number(rtos(Math::snapped(value, 0.001))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, accent); const String &formatted_offset = TranslationServer::get_singleton()->format_number(rtos(Math::snapped(offset, 0.0001)), lang);
draw_string(font, ep.point_rect.position + Vector2(8, -font->get_height(font_size) - 8), TTR("Time:") + " " + formatted_offset, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, accent);
const String &formatted_value = TranslationServer::get_singleton()->format_number(rtos(Math::snapped(value, 0.001)), lang);
draw_string(font, ep.point_rect.position + Vector2(8, -8), TTR("Value:") + " " + formatted_value, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, accent);
} else { } else {
Color track_color = Color(1, 1, 1, 1); Color track_color = Color(1, 1, 1, 1);
if (i != selected_track) { if (i != selected_track) {

View file

@ -34,6 +34,7 @@
#include "core/config/project_settings.h" #include "core/config/project_settings.h"
#include "core/error/error_macros.h" #include "core/error/error_macros.h"
#include "core/input/input.h" #include "core/input/input.h"
#include "core/string/translation_server.h"
#include "editor/animation/animation_bezier_editor.h" #include "editor/animation/animation_bezier_editor.h"
#include "editor/animation/animation_player_editor_plugin.h" #include "editor/animation/animation_player_editor_plugin.h"
#include "editor/docks/inspector_dock.h" #include "editor/docks/inspector_dock.h"
@ -2876,7 +2877,7 @@ String AnimationTrackEdit::get_tooltip(const Point2 &p_pos) const {
} }
if (key_idx != -1) { if (key_idx != -1) {
String text = TTR("Time (s):") + " " + TS->format_number(rtos(Math::snapped(animation->track_get_key_time(track, key_idx), SECOND_DECIMAL))) + "\n"; String text = TTR("Time (s):") + " " + TranslationServer::get_singleton()->format_number(rtos(Math::snapped(animation->track_get_key_time(track, key_idx), SECOND_DECIMAL)), _get_locale()) + "\n";
switch (animation->track_get_type(track)) { switch (animation->track_get_type(track)) {
case Animation::TYPE_POSITION_3D: { case Animation::TYPE_POSITION_3D: {
Vector3 t = animation->track_get_key_value(track, key_idx); Vector3 t = animation->track_get_key_value(track, key_idx);
@ -9011,7 +9012,7 @@ String AnimationMarkerEdit::get_tooltip(const Point2 &p_pos) const {
if (key_idx != -1) { if (key_idx != -1) {
String name = names[key_idx]; String name = names[key_idx];
String text = TTR("Time (s):") + " " + TS->format_number(rtos(Math::snapped(animation->get_marker_time(name), 0.0001))) + "\n"; String text = TTR("Time (s):") + " " + TranslationServer::get_singleton()->format_number(rtos(Math::snapped(animation->get_marker_time(name), 0.0001)), _get_locale()) + "\n";
text += TTR("Marker:") + " " + name + "\n"; text += TTR("Marker:") + " " + name + "\n";
return text; return text;
} }

View file

@ -30,6 +30,7 @@
#include "editor_performance_profiler.h" #include "editor_performance_profiler.h"
#include "core/string/translation_server.h"
#include "editor/editor_string_names.h" #include "editor/editor_string_names.h"
#include "editor/inspector/editor_property_name_processor.h" #include "editor/inspector/editor_property_name_processor.h"
#include "editor/settings/editor_settings.h" #include "editor/settings/editor_settings.h"
@ -45,29 +46,6 @@ EditorPerformanceProfiler::Monitor::Monitor(const String &p_name, const String &
base = p_base; base = p_base;
} }
void EditorPerformanceProfiler::Monitor::update_value(float p_value) {
ERR_FAIL_NULL(item);
String label = EditorPerformanceProfiler::_create_label(p_value, type);
String tooltip = label;
switch (type) {
case Performance::MONITOR_TYPE_MEMORY: {
tooltip = label;
} break;
case Performance::MONITOR_TYPE_TIME: {
tooltip = label;
} break;
default: {
tooltip += " " + item->get_text(0);
} break;
}
item->set_text(1, label);
item->set_tooltip_text(1, tooltip);
if (p_value > max) {
max = p_value;
}
}
void EditorPerformanceProfiler::Monitor::reset() { void EditorPerformanceProfiler::Monitor::reset() {
history.clear(); history.clear();
max = 0.0f; max = 0.0f;
@ -77,26 +55,53 @@ void EditorPerformanceProfiler::Monitor::reset() {
} }
} }
String EditorPerformanceProfiler::_create_label(float p_value, Performance::MonitorType p_type) { String EditorPerformanceProfiler::_format_label(float p_value, Performance::MonitorType p_type) const {
const String &lang = _get_locale();
const TranslationServer *ts = TranslationServer::get_singleton();
switch (p_type) { switch (p_type) {
case Performance::MONITOR_TYPE_QUANTITY: { case Performance::MONITOR_TYPE_QUANTITY: {
return TS->format_number(itos(p_value)); return ts->format_number(itos(p_value), lang);
} }
case Performance::MONITOR_TYPE_MEMORY: { case Performance::MONITOR_TYPE_MEMORY: {
return String::humanize_size(p_value); return String::humanize_size(p_value);
} }
case Performance::MONITOR_TYPE_TIME: { case Performance::MONITOR_TYPE_TIME: {
return TS->format_number(rtos(p_value * 1000).pad_decimals(2)) + " " + TTR("ms"); return ts->format_number(rtos(p_value * 1000).pad_decimals(2), lang) + " " + TTR("ms");
} }
case Performance::MONITOR_TYPE_PERCENTAGE: { case Performance::MONITOR_TYPE_PERCENTAGE: {
return TS->format_number(rtos(p_value * 100).pad_decimals(2)) + "%"; return ts->format_number(rtos(p_value * 100).pad_decimals(2), lang) + "%";
} }
default: { default: {
return TS->format_number(rtos(p_value)); return ts->format_number(rtos(p_value), lang);
} }
} }
} }
void EditorPerformanceProfiler::_update_monitor_value(Monitor *p_monitor, float p_value) {
TreeItem *item = p_monitor->item;
ERR_FAIL_NULL(item);
const String label = EditorPerformanceProfiler::_format_label(p_value, p_monitor->type);
item->set_text(1, label);
String tooltip;
switch (p_monitor->type) {
case Performance::MONITOR_TYPE_MEMORY:
case Performance::MONITOR_TYPE_TIME: {
item->set_tooltip_text(1, label);
} break;
default: {
item->set_tooltip_text(1, label + " " + item->get_text(0));
} break;
}
if (p_value > p_monitor->max) {
p_monitor->max = p_value;
}
}
void EditorPerformanceProfiler::_monitor_select() { void EditorPerformanceProfiler::_monitor_select() {
monitor_draw->queue_redraw(); monitor_draw->queue_redraw();
} }
@ -159,12 +164,12 @@ void EditorPerformanceProfiler::_monitor_draw() {
Color horizontal_line_color; Color horizontal_line_color;
horizontal_line_color.set_hsv(draw_color.get_h(), draw_color.get_s() * 0.5f, draw_color.get_v() * 0.5f, 0.3f); horizontal_line_color.set_hsv(draw_color.get_h(), draw_color.get_s() * 0.5f, draw_color.get_v() * 0.5f, 0.3f);
monitor_draw->draw_line(rect.position, rect.position + Vector2(rect.size.width, 0), horizontal_line_color, Math::round(EDSCALE)); monitor_draw->draw_line(rect.position, rect.position + Vector2(rect.size.width, 0), horizontal_line_color, Math::round(EDSCALE));
monitor_draw->draw_string(graph_font, rect.position + Vector2(0, graph_font->get_ascent(font_size)), _create_label(current.max, current.type), HORIZONTAL_ALIGNMENT_LEFT, rect.size.width, font_size, horizontal_line_color); monitor_draw->draw_string(graph_font, rect.position + Vector2(0, graph_font->get_ascent(font_size)), _format_label(current.max, current.type), HORIZONTAL_ALIGNMENT_LEFT, rect.size.width, font_size, horizontal_line_color);
for (int j = 0; j < line_count; j++) { for (int j = 0; j < line_count; j++) {
Vector2 y_offset = Vector2(0, rect.size.height * (1.0f - float(j) / float(line_count))); Vector2 y_offset = Vector2(0, rect.size.height * (1.0f - float(j) / float(line_count)));
monitor_draw->draw_line(rect.position + y_offset, rect.position + Vector2(rect.size.width, 0) + y_offset, horizontal_line_color, Math::round(EDSCALE)); monitor_draw->draw_line(rect.position + y_offset, rect.position + Vector2(rect.size.width, 0) + y_offset, horizontal_line_color, Math::round(EDSCALE));
monitor_draw->draw_string(graph_font, rect.position - Vector2(0, graph_font->get_descent(font_size)) + y_offset, _create_label(current.max * float(j) / float(line_count), current.type), HORIZONTAL_ALIGNMENT_LEFT, rect.size.width, font_size, horizontal_line_color); monitor_draw->draw_string(graph_font, rect.position - Vector2(0, graph_font->get_descent(font_size)) + y_offset, _format_label(current.max * float(j) / float(line_count), current.type), HORIZONTAL_ALIGNMENT_LEFT, rect.size.width, font_size, horizontal_line_color);
} }
} }
@ -189,7 +194,7 @@ void EditorPerformanceProfiler::_monitor_draw() {
line_color.set_hsv(draw_color.get_h(), draw_color.get_s() * 0.8f, draw_color.get_v(), 0.5f); line_color.set_hsv(draw_color.get_h(), draw_color.get_s() * 0.8f, draw_color.get_v(), 0.5f);
monitor_draw->draw_line(rect.position + Point2(from, 0), rect.position + Point2(from, rect.size.y), line_color, Math::round(EDSCALE)); monitor_draw->draw_line(rect.position + Point2(from, 0), rect.position + Point2(from, rect.size.y), line_color, Math::round(EDSCALE));
String label = _create_label(e->get(), current.type); String label = _format_label(e->get(), current.type);
Size2 size = graph_font->get_string_size(label, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size); Size2 size = graph_font->get_string_size(label, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
Vector2 text_top_left_position = Vector2(from, h2) - (size + Vector2(MARKER_MARGIN, MARKER_MARGIN)); Vector2 text_top_left_position = Vector2(from, h2) - (size + Vector2(MARKER_MARGIN, MARKER_MARGIN));
if (text_top_left_position.x < 0) { if (text_top_left_position.x < 0) {
@ -225,7 +230,7 @@ void EditorPerformanceProfiler::_build_monitor_tree() {
item->set_checked(0, monitor_checked.has(E.key)); item->set_checked(0, monitor_checked.has(E.key));
E.value.item = item; E.value.item = item;
if (!E.value.history.is_empty()) { if (!E.value.history.is_empty()) {
E.value.update_value(E.value.history.front()->get()); _update_monitor_value(&E.value, E.value.history.front()->get());
} }
} }
} }
@ -366,7 +371,7 @@ void EditorPerformanceProfiler::add_profile_frame(const Vector<float> &p_values)
value = p_values[E.value.frame_index]; value = p_values[E.value.frame_index];
} }
E.value.history.push_front(value); E.value.history.push_front(value);
E.value.update_value(value); _update_monitor_value(&E.value, value);
} }
marker_frame++; marker_frame++;
monitor_draw->queue_redraw(); monitor_draw->queue_redraw();

View file

@ -53,7 +53,6 @@ private:
Monitor() {} Monitor() {}
Monitor(const String &p_name, const String &p_base, int p_frame_index, Performance::MonitorType p_type, TreeItem *p_item); Monitor(const String &p_name, const String &p_base, int p_frame_index, Performance::MonitorType p_type, TreeItem *p_item);
void update_value(float p_value);
void reset(); void reset();
}; };
@ -69,7 +68,8 @@ private:
const int POINT_SEPARATION = 5; const int POINT_SEPARATION = 5;
const int MARKER_MARGIN = 2; const int MARKER_MARGIN = 2;
static String _create_label(float p_value, Performance::MonitorType p_type); String _format_label(float p_value, Performance::MonitorType p_type) const;
void _update_monitor_value(Monitor *p_monitor, float p_value);
void _monitor_select(); void _monitor_select();
void _monitor_draw(); void _monitor_draw();
void _build_monitor_tree(); void _build_monitor_tree();

View file

@ -31,6 +31,7 @@
#include "editor_profiler.h" #include "editor_profiler.h"
#include "core/io/image.h" #include "core/io/image.h"
#include "core/string/translation_server.h"
#include "editor/editor_string_names.h" #include "editor/editor_string_names.h"
#include "editor/run/editor_run_bar.h" #include "editor/run/editor_run_bar.h"
#include "editor/settings/editor_settings.h" #include "editor/settings/editor_settings.h"
@ -116,29 +117,31 @@ void EditorProfiler::clear() {
emit_signal(SNAME("enable_profiling"), activate->is_pressed()); emit_signal(SNAME("enable_profiling"), activate->is_pressed());
} }
static String _get_percent_txt(float p_value, float p_total) {
if (p_total == 0) {
p_total = 0.00001;
}
return TS->format_number(String::num((p_value / p_total) * 100, 1)) + TS->percent_sign();
}
String EditorProfiler::_get_time_as_text(const Metric &m, float p_time, int p_calls) { String EditorProfiler::_get_time_as_text(const Metric &m, float p_time, int p_calls) {
const int dmode = display_mode->get_selected(); const String &lang = _get_locale();
const TranslationServer *ts = TranslationServer::get_singleton();
if (dmode == DISPLAY_FRAME_TIME) { switch (display_mode->get_selected()) {
return TS->format_number(rtos(p_time * 1000).pad_decimals(2)) + " " + TTR("ms"); case DISPLAY_FRAME_TIME: {
} else if (dmode == DISPLAY_AVERAGE_TIME) { return ts->format_number(rtos(p_time * 1000).pad_decimals(2), lang) + " " + TTR("ms");
if (p_calls == 0) { } break;
return TS->format_number("0.00") + " " + TTR("ms");
} else { case DISPLAY_AVERAGE_TIME: {
return TS->format_number(rtos((p_time / p_calls) * 1000).pad_decimals(2)) + " " + TTR("ms"); if (p_calls == 0) {
} return ts->format_number("0.00", lang) + " " + TTR("ms");
} else if (dmode == DISPLAY_FRAME_PERCENT) { }
return _get_percent_txt(p_time, m.frame_time); return ts->format_number(rtos((p_time / p_calls) * 1000).pad_decimals(2), lang) + " " + TTR("ms");
} else if (dmode == DISPLAY_PHYSICS_FRAME_PERCENT) { } break;
return _get_percent_txt(p_time, m.physics_frame_time);
case DISPLAY_FRAME_PERCENT: {
float total = m.frame_time == 0 ? 0.00001 : m.frame_time;
return ts->format_number(String::num((p_time / total) * 100, 1), lang) + ts->get_percent_sign(lang);
} break;
case DISPLAY_PHYSICS_FRAME_PERCENT: {
float total = m.physics_frame_time == 0 ? 0.00001 : m.physics_frame_time;
return ts->format_number(String::num((p_time / total) * 100, 1), lang) + ts->get_percent_sign(lang);
} break;
} }
return "err"; return "err";

View file

@ -31,6 +31,7 @@
#include "editor_visual_profiler.h" #include "editor_visual_profiler.h"
#include "core/io/image.h" #include "core/io/image.h"
#include "core/string/translation_server.h"
#include "editor/editor_string_names.h" #include "editor/editor_string_names.h"
#include "editor/run/editor_run_bar.h" #include "editor/run/editor_run_bar.h"
#include "editor/settings/editor_settings.h" #include "editor/settings/editor_settings.h"
@ -123,12 +124,14 @@ void EditorVisualProfiler::clear() {
} }
String EditorVisualProfiler::_get_time_as_text(float p_time) { String EditorVisualProfiler::_get_time_as_text(float p_time) {
const String &lang = _get_locale();
int dmode = display_mode->get_selected(); int dmode = display_mode->get_selected();
if (dmode == DISPLAY_FRAME_TIME) { if (dmode == DISPLAY_FRAME_TIME) {
return TS->format_number(String::num(p_time, 2)) + " " + TTR("ms"); return TranslationServer::get_singleton()->format_number(String::num(p_time, 2), lang) + " " + TTR("ms");
} else if (dmode == DISPLAY_FRAME_PERCENT) { } else if (dmode == DISPLAY_FRAME_PERCENT) {
return TS->format_number(String::num(p_time * 100 / graph_limit, 2)) + " " + TS->percent_sign(); return TranslationServer::get_singleton()->format_number(String::num(p_time * 100 / graph_limit, 2), lang) + " " + TranslationServer::get_singleton()->get_percent_sign(lang);
} }
return "err"; return "err";

View file

@ -33,6 +33,7 @@
#include "core/input/input.h" #include "core/input/input.h"
#include "core/math/expression.h" #include "core/math/expression.h"
#include "core/os/keyboard.h" #include "core/os/keyboard.h"
#include "core/string/translation_server.h"
#include "editor/settings/editor_settings.h" #include "editor/settings/editor_settings.h"
#include "editor/themes/editor_scale.h" #include "editor/themes/editor_scale.h"
#include "scene/theme/theme_db.h" #include "scene/theme/theme_db.h"
@ -51,9 +52,7 @@ String EditorSpinSlider::get_tooltip(const Point2 &p_pos) const {
} }
String EditorSpinSlider::get_text_value() const { String EditorSpinSlider::get_text_value() const {
return TS->format_number(editing_integer return TranslationServer::get_singleton()->format_number(editing_integer ? itos(get_value()) : String::num(get_value(), Math::range_step_decimals(get_step())), _get_locale());
? itos(get_value())
: String::num(get_value(), Math::range_step_decimals(get_step())));
} }
void EditorSpinSlider::gui_input(const Ref<InputEvent> &p_event) { void EditorSpinSlider::gui_input(const Ref<InputEvent> &p_event) {
@ -582,19 +581,21 @@ String EditorSpinSlider::get_suffix() const {
} }
void EditorSpinSlider::_evaluate_input_text() { void EditorSpinSlider::_evaluate_input_text() {
const String &lang = _get_locale();
Ref<Expression> expr; Ref<Expression> expr;
expr.instantiate(); expr.instantiate();
// Convert commas ',' to dots '.' for French/German etc. keyboard layouts. // Convert commas ',' to dots '.' for French/German etc. keyboard layouts.
String text = value_input->get_text().replace_char(',', '.'); String text = value_input->get_text().replace_char(',', '.');
text = text.replace_char(';', ','); text = text.replace_char(';', ',');
text = TS->parse_number(text); text = TranslationServer::get_singleton()->parse_number(text, lang);
Error err = expr->parse(text); Error err = expr->parse(text);
if (err != OK) { if (err != OK) {
// If the expression failed try without converting commas to dots - they might have been for parameter separation. // If the expression failed try without converting commas to dots - they might have been for parameter separation.
text = value_input->get_text(); text = value_input->get_text();
text = TS->parse_number(text); text = TranslationServer::get_singleton()->parse_number(text, lang);
err = expr->parse(text); err = expr->parse(text);
if (err != OK) { if (err != OK) {

View file

@ -31,22 +31,25 @@
#include "editor_zoom_widget.h" #include "editor_zoom_widget.h"
#include "core/os/keyboard.h" #include "core/os/keyboard.h"
#include "core/string/translation_server.h"
#include "editor/settings/editor_settings.h" #include "editor/settings/editor_settings.h"
#include "editor/themes/editor_scale.h" #include "editor/themes/editor_scale.h"
void EditorZoomWidget::_update_zoom_label() { void EditorZoomWidget::_update_zoom_label() {
const String &lang = _get_locale();
String zoom_text; String zoom_text;
// The zoom level displayed is relative to the editor scale // The zoom level displayed is relative to the editor scale
// (like in most image editors). Its lower bound is clamped to 1 as some people // (like in most image editors). Its lower bound is clamped to 1 as some people
// lower the editor scale to increase the available real estate, // lower the editor scale to increase the available real estate,
// even if their display doesn't have a particularly low DPI. // even if their display doesn't have a particularly low DPI.
if (zoom >= 10) { if (zoom >= 10) {
zoom_text = TS->format_number(rtos(Math::round((zoom / MAX(1, EDSCALE)) * 100))); zoom_text = TranslationServer::get_singleton()->format_number(rtos(Math::round((zoom / MAX(1, EDSCALE)) * 100)), lang);
} else { } else {
// 2 decimal places if the zoom is below 10%, 1 decimal place if it's below 1000%. // 2 decimal places if the zoom is below 10%, 1 decimal place if it's below 1000%.
zoom_text = TS->format_number(rtos(Math::snapped((zoom / MAX(1, EDSCALE)) * 100, (zoom >= 0.1) ? 0.1 : 0.01))); zoom_text = TranslationServer::get_singleton()->format_number(rtos(Math::snapped((zoom / MAX(1, EDSCALE)) * 100, (zoom >= 0.1) ? 0.1 : 0.01)), lang);
} }
zoom_text += " " + TS->percent_sign(); zoom_text += " " + TranslationServer::get_singleton()->get_percent_sign(lang);
zoom_reset->set_text(zoom_text); zoom_reset->set_text(zoom_text);
} }

View file

@ -32,6 +32,7 @@
#include "core/config/project_settings.h" #include "core/config/project_settings.h"
#include "core/input/input_map.h" #include "core/input/input_map.h"
#include "core/string/translation_server.h"
#include "editor/docks/inspector_dock.h" #include "editor/docks/inspector_dock.h"
#include "editor/docks/scene_tree_dock.h" #include "editor/docks/scene_tree_dock.h"
#include "editor/editor_node.h" #include "editor/editor_node.h"
@ -1749,7 +1750,9 @@ void EditorPropertyEasing::_draw_easing() {
} else { } else {
decimals = 1; decimals = 1;
} }
f->draw_string(ci, Point2(10, 10 + f->get_ascent(font_size)), TS->format_number(rtos(exp).pad_decimals(decimals)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color);
const String &formatted = TranslationServer::get_singleton()->format_number(rtos(exp).pad_decimals(decimals), _get_locale());
f->draw_string(ci, Point2(10, 10 + f->get_ascent(font_size)), formatted, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color);
} }
void EditorPropertyEasing::update_property() { void EditorPropertyEasing::update_property() {
@ -1767,7 +1770,7 @@ void EditorPropertyEasing::_set_preset(int p_preset) {
void EditorPropertyEasing::_setup_spin() { void EditorPropertyEasing::_setup_spin() {
spin->setup_and_show(); spin->setup_and_show();
spin->get_line_edit()->set_text(TS->format_number(rtos(get_edited_property_value()))); spin->get_line_edit()->set_text(TranslationServer::get_singleton()->format_number(rtos(get_edited_property_value()), _get_locale()));
spin->show(); spin->show();
} }

View file

@ -36,6 +36,7 @@
#include "core/math/math_funcs.h" #include "core/math/math_funcs.h"
#include "core/math/projection.h" #include "core/math/projection.h"
#include "core/os/keyboard.h" #include "core/os/keyboard.h"
#include "core/string/translation_server.h"
#include "editor/animation/animation_player_editor_plugin.h" #include "editor/animation/animation_player_editor_plugin.h"
#include "editor/debugger/editor_debugger_node.h" #include "editor/debugger/editor_debugger_node.h"
#include "editor/docks/scene_tree_dock.h" #include "editor/docks/scene_tree_dock.h"
@ -3230,7 +3231,7 @@ void Node3DEditorViewport::_notification(int p_what) {
geometry->surface_end(); geometry->surface_end();
float distance = start_pos.distance_to(end_pos); float distance = start_pos.distance_to(end_pos);
ruler_label->set_text(TS->format_number(vformat("%.3f m", distance))); ruler_label->set_text(TranslationServer::get_singleton()->format_number(vformat("%.3f m", distance), _get_locale()));
Vector3 center = (start_pos + end_pos) / 2; Vector3 center = (start_pos + end_pos) / 2;
Vector2 screen_position = camera->unproject_position(center) - (ruler_label->get_custom_minimum_size() / 2); Vector2 screen_position = camera->unproject_position(center) - (ruler_label->get_custom_minimum_size() / 2);

View file

@ -33,6 +33,7 @@
#include "core/config/project_settings.h" #include "core/config/project_settings.h"
#include "core/input/input.h" #include "core/input/input.h"
#include "core/os/keyboard.h" #include "core/os/keyboard.h"
#include "core/string/translation_server.h"
#include "editor/animation/animation_player_editor_plugin.h" #include "editor/animation/animation_player_editor_plugin.h"
#include "editor/debugger/editor_debugger_node.h" #include "editor/debugger/editor_debugger_node.h"
#include "editor/docks/scene_tree_dock.h" #include "editor/docks/scene_tree_dock.h"
@ -3079,14 +3080,15 @@ void CanvasItemEditor::_draw_text_at_position(Point2 p_position, const String &p
} }
void CanvasItemEditor::_draw_margin_at_position(int p_value, Point2 p_position, Side p_side) { void CanvasItemEditor::_draw_margin_at_position(int p_value, Point2 p_position, Side p_side) {
String str = TS->format_number(vformat("%d " + TTR("px"), p_value)); String str = TranslationServer::get_singleton()->format_number(vformat("%d " + TTR("px"), p_value), _get_locale());
if (p_value != 0) { if (p_value != 0) {
_draw_text_at_position(p_position, str, p_side); _draw_text_at_position(p_position, str, p_side);
} }
} }
void CanvasItemEditor::_draw_percentage_at_position(real_t p_value, Point2 p_position, Side p_side) { void CanvasItemEditor::_draw_percentage_at_position(real_t p_value, Point2 p_position, Side p_side) {
String str = TS->format_number(vformat("%.1f ", p_value * 100.0)) + TS->percent_sign(); const String &lang = _get_locale();
String str = TranslationServer::get_singleton()->format_number(vformat("%.1f ", p_value * 100.0), lang) + TranslationServer::get_singleton()->get_percent_sign(lang);
if (p_value != 0) { if (p_value != 0) {
_draw_text_at_position(p_position, str, p_side); _draw_text_at_position(p_position, str, p_side);
} }
@ -3128,8 +3130,9 @@ void CanvasItemEditor::_draw_guides() {
Color text_color = get_theme_color(SceneStringName(font_color), EditorStringName(Editor)); Color text_color = get_theme_color(SceneStringName(font_color), EditorStringName(Editor));
Color outline_color = text_color.inverted(); Color outline_color = text_color.inverted();
const float outline_size = 2; const float outline_size = 2;
const String &lang = _get_locale();
if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_V_GUIDE) { if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_V_GUIDE) {
String str = TS->format_number(vformat("%d px", Math::round(xform.affine_inverse().xform(dragged_guide_pos).x))); String str = TranslationServer::get_singleton()->format_number(vformat("%d px", Math::round(xform.affine_inverse().xform(dragged_guide_pos).x)), lang);
Ref<Font> font = get_theme_font(SNAME("bold"), EditorStringName(EditorFonts)); Ref<Font> font = get_theme_font(SNAME("bold"), EditorStringName(EditorFonts));
int font_size = 1.3 * get_theme_font_size(SNAME("bold_size"), EditorStringName(EditorFonts)); int font_size = 1.3 * get_theme_font_size(SNAME("bold_size"), EditorStringName(EditorFonts));
Size2 text_size = font->get_string_size(str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size); Size2 text_size = font->get_string_size(str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
@ -3138,7 +3141,7 @@ void CanvasItemEditor::_draw_guides() {
viewport->draw_line(Point2(dragged_guide_pos.x, 0), Point2(dragged_guide_pos.x, viewport->get_size().y), guide_color, Math::round(EDSCALE)); viewport->draw_line(Point2(dragged_guide_pos.x, 0), Point2(dragged_guide_pos.x, viewport->get_size().y), guide_color, Math::round(EDSCALE));
} }
if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_H_GUIDE) { if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_H_GUIDE) {
String str = TS->format_number(vformat("%d px", Math::round(xform.affine_inverse().xform(dragged_guide_pos).y))); String str = TranslationServer::get_singleton()->format_number(vformat("%d px", Math::round(xform.affine_inverse().xform(dragged_guide_pos).y)), lang);
Ref<Font> font = get_theme_font(SNAME("bold"), EditorStringName(EditorFonts)); Ref<Font> font = get_theme_font(SNAME("bold"), EditorStringName(EditorFonts));
int font_size = 1.3 * get_theme_font_size(SNAME("bold_size"), EditorStringName(EditorFonts)); int font_size = 1.3 * get_theme_font_size(SNAME("bold_size"), EditorStringName(EditorFonts));
Size2 text_size = font->get_string_size(str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size); Size2 text_size = font->get_string_size(str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size);
@ -3169,6 +3172,7 @@ void CanvasItemEditor::_draw_rulers() {
font_color.a = 0.8; font_color.a = 0.8;
Ref<Font> font = get_theme_font(SNAME("rulers"), EditorStringName(EditorFonts)); Ref<Font> font = get_theme_font(SNAME("rulers"), EditorStringName(EditorFonts));
real_t ruler_tick_scale = ruler_width_scaled / 15.0; real_t ruler_tick_scale = ruler_width_scaled / 15.0;
const String lang = _get_locale();
// The rule transform // The rule transform
Transform2D ruler_transform; Transform2D ruler_transform;
@ -3215,7 +3219,8 @@ void CanvasItemEditor::_draw_rulers() {
if (i % (major_subdivision * minor_subdivision) == 0) { if (i % (major_subdivision * minor_subdivision) == 0) {
viewport->draw_line(Point2(position.x, 0), Point2(position.x, ruler_width_scaled), graduation_color, Math::round(EDSCALE)); viewport->draw_line(Point2(position.x, 0), Point2(position.x, ruler_width_scaled), graduation_color, Math::round(EDSCALE));
real_t val = (ruler_transform * major_subdivide * minor_subdivide).xform(Point2(i, 0)).x; real_t val = (ruler_transform * major_subdivide * minor_subdivide).xform(Point2(i, 0)).x;
viewport->draw_string(font, Point2(position.x + MAX(Math::round(ruler_font_size / 8.0), 2), font->get_ascent(ruler_font_size) + Math::round(EDSCALE)), TS->format_number(vformat(((int)val == val) ? "%d" : "%.1f", val)), HORIZONTAL_ALIGNMENT_LEFT, -1, ruler_font_size, font_color); const String &formatted = TranslationServer::get_singleton()->format_number(vformat(((int)val == val) ? "%d" : "%.1f", val), lang);
viewport->draw_string(font, Point2(position.x + MAX(Math::round(ruler_font_size / 8.0), 2), font->get_ascent(ruler_font_size) + Math::round(EDSCALE)), formatted, HORIZONTAL_ALIGNMENT_LEFT, -1, ruler_font_size, font_color);
} else { } else {
if (i % minor_subdivision == 0) { if (i % minor_subdivision == 0) {
viewport->draw_line(Point2(position.x, ruler_width_scaled * 0.33), Point2(position.x, ruler_width_scaled), graduation_color, Math::round(EDSCALE)); viewport->draw_line(Point2(position.x, ruler_width_scaled * 0.33), Point2(position.x, ruler_width_scaled), graduation_color, Math::round(EDSCALE));
@ -3235,7 +3240,8 @@ void CanvasItemEditor::_draw_rulers() {
Transform2D text_xform = Transform2D(-Math::PI / 2.0, Point2(font->get_ascent(ruler_font_size) + Math::round(EDSCALE), position.y - 2)); Transform2D text_xform = Transform2D(-Math::PI / 2.0, Point2(font->get_ascent(ruler_font_size) + Math::round(EDSCALE), position.y - 2));
viewport->draw_set_transform_matrix(viewport->get_transform() * text_xform); viewport->draw_set_transform_matrix(viewport->get_transform() * text_xform);
viewport->draw_string(font, Point2(), TS->format_number(vformat(((int)val == val) ? "%d" : "%.1f", val)), HORIZONTAL_ALIGNMENT_LEFT, -1, ruler_font_size, font_color); const String &formatted = TranslationServer::get_singleton()->format_number(vformat(((int)val == val) ? "%d" : "%.1f", val), lang);
viewport->draw_string(font, Point2(), formatted, HORIZONTAL_ALIGNMENT_LEFT, -1, ruler_font_size, font_color);
viewport->draw_set_transform_matrix(viewport->get_transform()); viewport->draw_set_transform_matrix(viewport->get_transform());
} else { } else {
@ -3330,6 +3336,9 @@ void CanvasItemEditor::_draw_ruler_tool() {
const Ref<Texture2D> position_icon = get_editor_theme_icon(SNAME("EditorPosition")); const Ref<Texture2D> position_icon = get_editor_theme_icon(SNAME("EditorPosition"));
if (ruler_tool_active) { if (ruler_tool_active) {
const String &lang = _get_locale();
const TranslationServer *ts = TranslationServer::get_singleton();
Color ruler_primary_color = get_theme_color(SNAME("accent_color"), EditorStringName(Editor)); Color ruler_primary_color = get_theme_color(SNAME("accent_color"), EditorStringName(Editor));
Color ruler_secondary_color = ruler_primary_color; Color ruler_secondary_color = ruler_primary_color;
ruler_secondary_color.a = 0.5; ruler_secondary_color.a = 0.5;
@ -3401,8 +3410,8 @@ void CanvasItemEditor::_draw_ruler_tool() {
return; return;
} }
viewport->draw_string_outline(font, text_pos, TS->format_number(vformat("%.1f px", length_vector.length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); viewport->draw_string_outline(font, text_pos, ts->format_number(vformat("%.1f px", length_vector.length()), lang), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, text_pos, TS->format_number(vformat("%.1f px", length_vector.length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color); viewport->draw_string(font, text_pos, ts->format_number(vformat("%.1f px", length_vector.length()), lang), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color);
if (draw_secondary_lines) { if (draw_secondary_lines) {
const int horizontal_angle = std::round(180 * horizontal_angle_rad / Math::PI); const int horizontal_angle = std::round(180 * horizontal_angle_rad / Math::PI);
@ -3410,19 +3419,19 @@ void CanvasItemEditor::_draw_ruler_tool() {
Point2 text_pos2 = text_pos; Point2 text_pos2 = text_pos;
text_pos2.x = begin.x < text_pos.x ? MIN(text_pos.x - text_width, begin.x - text_width / 2) : MAX(text_pos.x + text_width, begin.x - text_width / 2); text_pos2.x = begin.x < text_pos.x ? MIN(text_pos.x - text_width, begin.x - text_width / 2) : MAX(text_pos.x + text_width, begin.x - text_width / 2);
viewport->draw_string_outline(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.y)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); viewport->draw_string_outline(font, text_pos2, ts->format_number(vformat("%.1f px", length_vector.y), lang), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.y)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color); viewport->draw_string(font, text_pos2, ts->format_number(vformat("%.1f px", length_vector.y), lang), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color);
Point2 v_angle_text_pos; Point2 v_angle_text_pos;
v_angle_text_pos.x = CLAMP(begin.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width); v_angle_text_pos.x = CLAMP(begin.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width);
v_angle_text_pos.y = begin.y < end.y ? MIN(text_pos2.y - 2 * text_height, begin.y - text_height * 0.5) : MAX(text_pos2.y + text_height * 3, begin.y + text_height * 1.5); v_angle_text_pos.y = begin.y < end.y ? MIN(text_pos2.y - 2 * text_height, begin.y - text_height * 0.5) : MAX(text_pos2.y + text_height * 3, begin.y + text_height * 1.5);
viewport->draw_string_outline(font, v_angle_text_pos, TS->format_number(vformat(U"%d°", vertical_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); viewport->draw_string_outline(font, v_angle_text_pos, ts->format_number(vformat(U"%d°", vertical_angle), lang), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, v_angle_text_pos, TS->format_number(vformat(U"%d°", vertical_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color); viewport->draw_string(font, v_angle_text_pos, ts->format_number(vformat(U"%d°", vertical_angle), lang), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color);
text_pos2 = text_pos; text_pos2 = text_pos;
text_pos2.y = end.y < text_pos.y ? MIN(text_pos.y - text_height * 2, end.y - text_height / 2) : MAX(text_pos.y + text_height * 2, end.y - text_height / 2); text_pos2.y = end.y < text_pos.y ? MIN(text_pos.y - text_height * 2, end.y - text_height / 2) : MAX(text_pos.y + text_height * 2, end.y - text_height / 2);
viewport->draw_string_outline(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.x)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); viewport->draw_string_outline(font, text_pos2, ts->format_number(vformat("%.1f px", length_vector.x), lang), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.x)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color); viewport->draw_string(font, text_pos2, ts->format_number(vformat("%.1f px", length_vector.x), lang), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color);
Point2 h_angle_text_pos; Point2 h_angle_text_pos;
h_angle_text_pos.x = CLAMP(end.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width); h_angle_text_pos.x = CLAMP(end.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width);
@ -3439,8 +3448,8 @@ void CanvasItemEditor::_draw_ruler_tool() {
h_angle_text_pos.y = MIN(text_pos.y - height_multiplier * text_height, MIN(end.y - text_height * 0.5, text_pos2.y - height_multiplier * text_height)); h_angle_text_pos.y = MIN(text_pos.y - height_multiplier * text_height, MIN(end.y - text_height * 0.5, text_pos2.y - height_multiplier * text_height));
} }
} }
viewport->draw_string_outline(font, h_angle_text_pos, TS->format_number(vformat(U"%d°", horizontal_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); viewport->draw_string_outline(font, h_angle_text_pos, ts->format_number(vformat(U"%d°", horizontal_angle), lang), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, h_angle_text_pos, TS->format_number(vformat(U"%d°", horizontal_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color); viewport->draw_string(font, h_angle_text_pos, ts->format_number(vformat(U"%d°", horizontal_angle), lang), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color);
} }
if (grid_snap_active) { if (grid_snap_active) {
@ -3449,21 +3458,21 @@ void CanvasItemEditor::_draw_ruler_tool() {
text_pos.y = CLAMP(text_pos.y, text_height * 2.5, viewport->get_rect().size.y - text_height / 2); text_pos.y = CLAMP(text_pos.y, text_height * 2.5, viewport->get_rect().size.y - text_height / 2);
if (draw_secondary_lines) { if (draw_secondary_lines) {
viewport->draw_string_outline(font, text_pos, TS->format_number(vformat("%.2f " + TTR("units"), (length_vector / grid_step).length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); viewport->draw_string_outline(font, text_pos, ts->format_number(vformat("%.2f " + TTR("units"), (length_vector / grid_step).length()), lang), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, text_pos, TS->format_number(vformat("%.2f " + TTR("units"), (length_vector / grid_step).length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color); viewport->draw_string(font, text_pos, ts->format_number(vformat("%.2f " + TTR("units"), (length_vector / grid_step).length()), lang), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color);
Point2 text_pos2 = text_pos; Point2 text_pos2 = text_pos;
text_pos2.x = begin.x < text_pos.x ? MIN(text_pos.x - text_width, begin.x - text_width / 2) : MAX(text_pos.x + text_width, begin.x - text_width / 2); text_pos2.x = begin.x < text_pos.x ? MIN(text_pos.x - text_width, begin.x - text_width / 2) : MAX(text_pos.x + text_width, begin.x - text_width / 2);
viewport->draw_string_outline(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), std::round(length_vector.y / grid_step.y))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); viewport->draw_string_outline(font, text_pos2, ts->format_number(vformat("%d " + TTR("units"), std::round(length_vector.y / grid_step.y)), lang), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), std::round(length_vector.y / grid_step.y))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color); viewport->draw_string(font, text_pos2, ts->format_number(vformat("%d " + TTR("units"), std::round(length_vector.y / grid_step.y)), lang), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color);
text_pos2 = text_pos; text_pos2 = text_pos;
text_pos2.y = end.y < text_pos.y ? MIN(text_pos.y - text_height * 2, end.y + text_height / 2) : MAX(text_pos.y + text_height * 2, end.y + text_height / 2); text_pos2.y = end.y < text_pos.y ? MIN(text_pos.y - text_height * 2, end.y + text_height / 2) : MAX(text_pos.y + text_height * 2, end.y + text_height / 2);
viewport->draw_string_outline(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), std::round(length_vector.x / grid_step.x))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); viewport->draw_string_outline(font, text_pos2, ts->format_number(vformat("%d " + TTR("units"), std::round(length_vector.x / grid_step.x)), lang), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), std::round(length_vector.x / grid_step.x))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color); viewport->draw_string(font, text_pos2, ts->format_number(vformat("%d " + TTR("units"), std::round(length_vector.x / grid_step.x)), lang), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color);
} else { } else {
viewport->draw_string_outline(font, text_pos, TS->format_number(vformat("%d " + TTR("units"), std::round((length_vector / grid_step).length()))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); viewport->draw_string_outline(font, text_pos, ts->format_number(vformat("%d " + TTR("units"), std::round((length_vector / grid_step).length())), lang), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color);
viewport->draw_string(font, text_pos, TS->format_number(vformat("%d " + TTR("units"), std::round((length_vector / grid_step).length()))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color); viewport->draw_string(font, text_pos, ts->format_number(vformat("%d " + TTR("units"), std::round((length_vector / grid_step).length())), lang), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color);
} }
} }
} else { } else {
@ -4061,7 +4070,8 @@ void CanvasItemEditor::_draw_message() {
double snap = EDITOR_GET("interface/inspector/default_float_step"); double snap = EDITOR_GET("interface/inspector/default_float_step");
int snap_step_decimals = Math::range_step_decimals(snap); int snap_step_decimals = Math::range_step_decimals(snap);
#define FORMAT(value) (TS->format_number(String::num(value, snap_step_decimals))) const String &lang = _get_locale();
#define FORMAT(value) (TranslationServer::get_singleton()->format_number(String::num(value, snap_step_decimals), lang))
switch (drag_type) { switch (drag_type) {
case DRAG_MOVE: case DRAG_MOVE:
@ -6391,7 +6401,8 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian
} else { } else {
double snap = EDITOR_GET("interface/inspector/default_float_step"); double snap = EDITOR_GET("interface/inspector/default_float_step");
int snap_step_decimals = Math::range_step_decimals(snap); int snap_step_decimals = Math::range_step_decimals(snap);
#define FORMAT(value) (TS->format_number(String::num(value, snap_step_decimals))) const String &lang = _get_locale();
#define FORMAT(value) (TranslationServer::get_singleton()->format_number(String::num(value, snap_step_decimals), lang))
Vector2 preview_node_pos = preview_node->get_global_position(); Vector2 preview_node_pos = preview_node->get_global_position();
canvas_item_editor->message = TTR("Instantiating: ") + "(" + FORMAT(preview_node_pos.x) + ", " + FORMAT(preview_node_pos.y) + ") px"; canvas_item_editor->message = TTR("Instantiating: ") + "(" + FORMAT(preview_node_pos.x) + ", " + FORMAT(preview_node_pos.y) + ") px";
} }

View file

@ -7509,258 +7509,6 @@ double TextServerAdvanced::_shaped_text_get_underline_thickness(const RID &p_sha
return sd->uthk; return sd->uthk;
} }
void TextServerAdvanced::_insert_num_systems_lang() {
// Eastern Arabic numerals.
{
NumSystemData ar;
ar.lang.insert(StringName("ar")); // Arabic
ar.lang.insert(StringName("ar_AE"));
ar.lang.insert(StringName("ar_BH"));
ar.lang.insert(StringName("ar_DJ"));
ar.lang.insert(StringName("ar_EG"));
ar.lang.insert(StringName("ar_ER"));
ar.lang.insert(StringName("ar_IL"));
ar.lang.insert(StringName("ar_IQ"));
ar.lang.insert(StringName("ar_JO"));
ar.lang.insert(StringName("ar_KM"));
ar.lang.insert(StringName("ar_KW"));
ar.lang.insert(StringName("ar_LB"));
ar.lang.insert(StringName("ar_MR"));
ar.lang.insert(StringName("ar_OM"));
ar.lang.insert(StringName("ar_PS"));
ar.lang.insert(StringName("ar_QA"));
ar.lang.insert(StringName("ar_SA"));
ar.lang.insert(StringName("ar_SD"));
ar.lang.insert(StringName("ar_SO"));
ar.lang.insert(StringName("ar_SS"));
ar.lang.insert(StringName("ar_SY"));
ar.lang.insert(StringName("ar_TD"));
ar.lang.insert(StringName("ar_YE"));
ar.lang.insert(StringName("ckb")); // Central Kurdish
ar.lang.insert(StringName("ckb_IQ"));
ar.lang.insert(StringName("ckb_IR"));
ar.lang.insert(StringName("sd")); // Sindhi
ar.lang.insert(StringName("sd_PK"));
ar.lang.insert(StringName("sd_Arab"));
ar.lang.insert(StringName("sd_Arab_PK"));
ar.digits = U"٠١٢٣٤٥٦٧٨٩٫";
ar.percent_sign = U"٪";
ar.exp_l = U"اس";
ar.exp_u = U"اس";
num_systems.push_back(ar);
}
// Persian and Urdu numerals.
{
NumSystemData pr;
pr.lang.insert(StringName("fa")); // Persian
pr.lang.insert(StringName("fa_AF"));
pr.lang.insert(StringName("fa_IR"));
pr.lang.insert(StringName("ks")); // Kashmiri
pr.lang.insert(StringName("ks_IN"));
pr.lang.insert(StringName("ks_Arab"));
pr.lang.insert(StringName("ks_Arab_IN"));
pr.lang.insert(StringName("lrc")); // Northern Luri
pr.lang.insert(StringName("lrc_IQ"));
pr.lang.insert(StringName("lrc_IR"));
pr.lang.insert(StringName("mzn")); // Mazanderani
pr.lang.insert(StringName("mzn_IR"));
pr.lang.insert(StringName("pa_PK")); // Panjabi
pr.lang.insert(StringName("pa_Arab"));
pr.lang.insert(StringName("pa_Arab_PK"));
pr.lang.insert(StringName("ps")); // Pushto
pr.lang.insert(StringName("ps_AF"));
pr.lang.insert(StringName("ps_PK"));
pr.lang.insert(StringName("ur_IN")); // Urdu
pr.lang.insert(StringName("uz_AF")); // Uzbek
pr.lang.insert(StringName("uz_Arab"));
pr.lang.insert(StringName("uz_Arab_AF"));
pr.digits = U"۰۱۲۳۴۵۶۷۸۹٫";
pr.percent_sign = U"٪";
pr.exp_l = U"اس";
pr.exp_u = U"اس";
num_systems.push_back(pr);
}
// Bengali numerals.
{
NumSystemData bn;
bn.lang.insert(StringName("as")); // Assamese
bn.lang.insert(StringName("as_IN"));
bn.lang.insert(StringName("bn")); // Bengali
bn.lang.insert(StringName("bn_BD"));
bn.lang.insert(StringName("bn_IN"));
bn.lang.insert(StringName("mni")); // Manipuri
bn.lang.insert(StringName("mni_IN"));
bn.lang.insert(StringName("mni_Beng"));
bn.lang.insert(StringName("mni_Beng_IN"));
bn.digits = U"০১২৩৪৫৬৭৮৯.";
bn.percent_sign = U"%";
bn.exp_l = U"e";
bn.exp_u = U"E";
num_systems.push_back(bn);
}
// Devanagari numerals.
{
NumSystemData mr;
mr.lang.insert(StringName("mr")); // Marathi
mr.lang.insert(StringName("mr_IN"));
mr.lang.insert(StringName("ne")); // Nepali
mr.lang.insert(StringName("ne_IN"));
mr.lang.insert(StringName("ne_NP"));
mr.lang.insert(StringName("sa")); // Sanskrit
mr.lang.insert(StringName("sa_IN"));
mr.digits = U"०१२३४५६७८९.";
mr.percent_sign = U"%";
mr.exp_l = U"e";
mr.exp_u = U"E";
num_systems.push_back(mr);
}
// Dzongkha numerals.
{
NumSystemData dz;
dz.lang.insert(StringName("dz")); // Dzongkha
dz.lang.insert(StringName("dz_BT"));
dz.digits = U"༠༡༢༣༤༥༦༧༨༩.";
dz.percent_sign = U"%";
dz.exp_l = U"e";
dz.exp_u = U"E";
num_systems.push_back(dz);
}
// Santali numerals.
{
NumSystemData sat;
sat.lang.insert(StringName("sat")); // Santali
sat.lang.insert(StringName("sat_IN"));
sat.lang.insert(StringName("sat_Olck"));
sat.lang.insert(StringName("sat_Olck_IN"));
sat.digits = U"᱐᱑᱒᱓᱔᱕᱖᱗᱘᱙.";
sat.percent_sign = U"%";
sat.exp_l = U"e";
sat.exp_u = U"E";
num_systems.push_back(sat);
}
// Burmese numerals.
{
NumSystemData my;
my.lang.insert(StringName("my")); // Burmese
my.lang.insert(StringName("my_MM"));
my.digits = U"၀၁၂၃၄၅၆၇၈၉.";
my.percent_sign = U"%";
my.exp_l = U"e";
my.exp_u = U"E";
num_systems.push_back(my);
}
// Chakma numerals.
{
NumSystemData ccp;
ccp.lang.insert(StringName("ccp")); // Chakma
ccp.lang.insert(StringName("ccp_BD"));
ccp.lang.insert(StringName("ccp_IN"));
ccp.digits = U"𑄶𑄷𑄸𑄹𑄺𑄻𑄼𑄽𑄾𑄿.";
ccp.percent_sign = U"%";
ccp.exp_l = U"e";
ccp.exp_u = U"E";
num_systems.push_back(ccp);
}
// Adlam numerals.
{
NumSystemData ff;
ff.lang.insert(StringName("ff")); // Fulah
ff.lang.insert(StringName("ff_Adlm_BF"));
ff.lang.insert(StringName("ff_Adlm_CM"));
ff.lang.insert(StringName("ff_Adlm_GH"));
ff.lang.insert(StringName("ff_Adlm_GM"));
ff.lang.insert(StringName("ff_Adlm_GN"));
ff.lang.insert(StringName("ff_Adlm_GW"));
ff.lang.insert(StringName("ff_Adlm_LR"));
ff.lang.insert(StringName("ff_Adlm_MR"));
ff.lang.insert(StringName("ff_Adlm_NE"));
ff.lang.insert(StringName("ff_Adlm_NG"));
ff.lang.insert(StringName("ff_Adlm_SL"));
ff.lang.insert(StringName("ff_Adlm_SN"));
ff.digits = U"𞥐𞥑𞥒𞥓𞥔𞥕𞥖𞥗𞥘𞥙.";
ff.percent_sign = U"%";
ff.exp_l = U"𞤉";
ff.exp_u = U"𞤉";
num_systems.push_back(ff);
}
}
String TextServerAdvanced::_format_number(const String &p_string, const String &p_language) const {
const StringName lang = (p_language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale() : p_language;
String res = p_string;
for (int i = 0; i < num_systems.size(); i++) {
if (num_systems[i].lang.has(lang)) {
if (num_systems[i].digits.is_empty()) {
return p_string;
}
res = res.replace("e", num_systems[i].exp_l);
res = res.replace("E", num_systems[i].exp_u);
char32_t *data = res.ptrw();
for (int j = 0; j < res.length(); j++) {
if (data[j] >= 0x30 && data[j] <= 0x39) {
data[j] = num_systems[i].digits[data[j] - 0x30];
} else if (data[j] == '.' || data[j] == ',') {
data[j] = num_systems[i].digits[10];
}
}
break;
}
}
return res;
}
String TextServerAdvanced::_parse_number(const String &p_string, const String &p_language) const {
const StringName lang = (p_language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale() : p_language;
String res = p_string;
for (int i = 0; i < num_systems.size(); i++) {
if (num_systems[i].lang.has(lang)) {
if (num_systems[i].digits.is_empty()) {
return p_string;
}
res = res.replace(num_systems[i].exp_l, "e");
res = res.replace(num_systems[i].exp_u, "E");
char32_t *data = res.ptrw();
for (int j = 0; j < res.length(); j++) {
if (data[j] == num_systems[i].digits[10]) {
data[j] = '.';
} else {
for (int k = 0; k < 10; k++) {
if (data[j] == num_systems[i].digits[k]) {
data[j] = 0x30 + k;
}
}
}
}
break;
}
}
return res;
}
String TextServerAdvanced::_percent_sign(const String &p_language) const {
const StringName lang = (p_language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale() : p_language;
for (int i = 0; i < num_systems.size(); i++) {
if (num_systems[i].lang.has(lang)) {
if (num_systems[i].percent_sign.is_empty()) {
return "%";
}
return num_systems[i].percent_sign;
}
}
return "%";
}
int64_t TextServerAdvanced::_is_confusable(const String &p_string, const PackedStringArray &p_dict) const { int64_t TextServerAdvanced::_is_confusable(const String &p_string, const PackedStringArray &p_dict) const {
#ifndef ICU_STATIC_DATA #ifndef ICU_STATIC_DATA
if (!icu_data_loaded) { if (!icu_data_loaded) {
@ -8316,7 +8064,6 @@ void TextServerAdvanced::_update_settings() {
} }
TextServerAdvanced::TextServerAdvanced() { TextServerAdvanced::TextServerAdvanced() {
_insert_num_systems_lang();
_insert_feature_sets(); _insert_feature_sets();
_bmp_create_font_funcs(); _bmp_create_font_funcs();
_update_settings(); _update_settings();

View file

@ -143,16 +143,6 @@ class TextServerAdvanced : public TextServerExtension {
GDCLASS(TextServerAdvanced, TextServerExtension); GDCLASS(TextServerAdvanced, TextServerExtension);
_THREAD_SAFE_CLASS_ _THREAD_SAFE_CLASS_
struct NumSystemData {
HashSet<StringName> lang;
String digits;
String percent_sign;
String exp_l;
String exp_u;
};
Vector<NumSystemData> num_systems;
struct FeatureInfo { struct FeatureInfo {
StringName name; StringName name;
Variant::Type vtype = Variant::INT; Variant::Type vtype = Variant::INT;
@ -173,7 +163,6 @@ class TextServerAdvanced : public TextServerExtension {
LineBreakStrictness lb_strictness = LB_AUTO; LineBreakStrictness lb_strictness = LB_AUTO;
void _update_settings(); void _update_settings();
void _insert_num_systems_lang();
void _insert_feature_sets(); void _insert_feature_sets();
_FORCE_INLINE_ void _insert_feature(const StringName &p_name, int32_t p_tag, Variant::Type p_vtype = Variant::INT, bool p_hidden = false); _FORCE_INLINE_ void _insert_feature(const StringName &p_name, int32_t p_tag, Variant::Type p_vtype = Variant::INT, bool p_hidden = false);
@ -1121,10 +1110,6 @@ public:
MODBIND1RC(PackedInt32Array, shaped_text_get_character_breaks, const RID &); MODBIND1RC(PackedInt32Array, shaped_text_get_character_breaks, const RID &);
MODBIND2RC(String, format_number, const String &, const String &);
MODBIND2RC(String, parse_number, const String &, const String &);
MODBIND1RC(String, percent_sign, const String &);
MODBIND3RC(PackedInt32Array, string_get_word_breaks, const String &, const String &, int64_t); MODBIND3RC(PackedInt32Array, string_get_word_breaks, const String &, const String &, int64_t);
MODBIND2RC(PackedInt32Array, string_get_character_breaks, const String &, const String &); MODBIND2RC(PackedInt32Array, string_get_character_breaks, const String &, const String &);

View file

@ -34,6 +34,7 @@
#include "core/config/project_settings.h" #include "core/config/project_settings.h"
#include "core/os/keyboard.h" #include "core/os/keyboard.h"
#include "core/string/string_builder.h" #include "core/string/string_builder.h"
#include "core/string/translation_server.h"
#include "core/string/ustring.h" #include "core/string/ustring.h"
#include "scene/theme/theme_db.h" #include "scene/theme/theme_db.h"
@ -1545,7 +1546,7 @@ void CodeEdit::_line_number_draw_callback(int p_line, int p_gutter, const Rect2
const String &lang = _get_locale(); const String &lang = _get_locale();
String fc = String::num_int64(p_line + 1).lpad(line_number_digits, line_number_padding); String fc = String::num_int64(p_line + 1).lpad(line_number_digits, line_number_padding);
if (is_localizing_numeral_system()) { if (is_localizing_numeral_system()) {
fc = TS->format_number(fc, lang); fc = TranslationServer::get_singleton()->format_number(fc, lang);
} }
text_rid = TS->create_shaped_text(); text_rid = TS->create_shaped_text();

View file

@ -30,6 +30,7 @@
#include "progress_bar.h" #include "progress_bar.h"
#include "core/string/translation_server.h"
#include "scene/resources/text_line.h" #include "scene/resources/text_line.h"
#include "scene/theme/theme_db.h" #include "scene/theme/theme_db.h"
@ -168,7 +169,7 @@ void ProgressBar::_notification(int p_what) {
if (is_localizing_numeral_system()) { if (is_localizing_numeral_system()) {
const String &lang = _get_locale(); const String &lang = _get_locale();
txt = TS->format_number(txt, lang) + TS->percent_sign(lang); txt = TranslationServer::get_singleton()->format_number(txt, lang) + TranslationServer::get_singleton()->get_percent_sign(lang);
} else { } else {
txt += String("%"); txt += String("%");
} }

View file

@ -36,6 +36,7 @@
#include "core/math/math_defs.h" #include "core/math/math_defs.h"
#include "core/os/keyboard.h" #include "core/os/keyboard.h"
#include "core/os/os.h" #include "core/os/os.h"
#include "core/string/translation_server.h"
#include "scene/gui/label.h" #include "scene/gui/label.h"
#include "scene/gui/rich_text_effect.h" #include "scene/gui/rich_text_effect.h"
#include "scene/main/timer.h" #include "scene/main/timer.h"
@ -252,7 +253,7 @@ String RichTextLabel::_get_prefix(Item *p_item, const Vector<int> &p_list_index,
if (p_list_items[i]->list_type == LIST_NUMBERS) { if (p_list_items[i]->list_type == LIST_NUMBERS) {
segment = itos(p_list_index[i]); segment = itos(p_list_index[i]);
if (is_localizing_numeral_system()) { if (is_localizing_numeral_system()) {
segment = TS->format_number(segment, _find_language(p_item)); segment = TranslationServer::get_singleton()->format_number(segment, _find_language(p_item));
} }
segments++; segments++;
} else if (p_list_items[i]->list_type == LIST_LETTERS) { } else if (p_list_items[i]->list_type == LIST_LETTERS) {

View file

@ -32,6 +32,7 @@
#include "core/input/input.h" #include "core/input/input.h"
#include "core/math/expression.h" #include "core/math/expression.h"
#include "core/string/translation_server.h"
#include "scene/theme/theme_db.h" #include "scene/theme/theme_db.h"
void SpinBoxLineEdit::_accessibility_action_inc(const Variant &p_data) { void SpinBoxLineEdit::_accessibility_action_inc(const Variant &p_data) {
@ -88,7 +89,7 @@ void SpinBox::_update_text(bool p_only_update_if_value_changed) {
double step = get_step(); double step = get_step();
String value = String::num(get_value(), Math::range_step_decimals(step)); String value = String::num(get_value(), Math::range_step_decimals(step));
if (is_localizing_numeral_system()) { if (is_localizing_numeral_system()) {
value = TS->format_number(value, _get_locale()); value = TranslationServer::get_singleton()->format_number(value, _get_locale());
} }
if (p_only_update_if_value_changed && value == last_text_value) { if (p_only_update_if_value_changed && value == last_text_value) {
@ -139,7 +140,7 @@ void SpinBox::_text_submitted(const String &p_string) {
const String &lang = _get_locale(); const String &lang = _get_locale();
text = text.replace_char(';', ','); text = text.replace_char(';', ',');
text = TS->parse_number(text, lang); text = TranslationServer::get_singleton()->parse_number(text, lang);
// Ignore the prefix and suffix in the expression. // Ignore the prefix and suffix in the expression.
text = text.trim_prefix(prefix + " ").trim_suffix(" " + suffix); text = text.trim_prefix(prefix + " ").trim_suffix(" " + suffix);
@ -148,7 +149,7 @@ void SpinBox::_text_submitted(const String &p_string) {
if (err != OK) { if (err != OK) {
// If the expression failed try without converting commas to dots - they might have been for parameter separation. // If the expression failed try without converting commas to dots - they might have been for parameter separation.
text = p_string; text = p_string;
text = TS->parse_number(text, lang); text = TranslationServer::get_singleton()->parse_number(text, lang);
text = text.trim_prefix(prefix + " ").trim_suffix(" " + suffix); text = text.trim_prefix(prefix + " ").trim_suffix(" " + suffix);
err = expr->parse(text); err = expr->parse(text);

View file

@ -36,6 +36,10 @@
#include "core/variant/typed_array.h" #include "core/variant/typed_array.h"
#include "servers/rendering/rendering_server.h" #include "servers/rendering/rendering_server.h"
#ifndef DISABLE_DEPRECATED
#include "core/string/translation_server.h"
#endif // DISABLE_DEPRECATED
TextServerManager *TextServerManager::singleton = nullptr; TextServerManager *TextServerManager::singleton = nullptr;
void TextServerManager::_bind_methods() { void TextServerManager::_bind_methods() {
@ -507,9 +511,11 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shaped_text_get_dominant_direction_in_range", "shaped", "start", "end"), &TextServer::shaped_text_get_dominant_direction_in_range); ClassDB::bind_method(D_METHOD("shaped_text_get_dominant_direction_in_range", "shaped", "start", "end"), &TextServer::shaped_text_get_dominant_direction_in_range);
#ifndef DISABLE_DEPRECATED
ClassDB::bind_method(D_METHOD("format_number", "number", "language"), &TextServer::format_number, DEFVAL("")); ClassDB::bind_method(D_METHOD("format_number", "number", "language"), &TextServer::format_number, DEFVAL(""));
ClassDB::bind_method(D_METHOD("parse_number", "number", "language"), &TextServer::parse_number, DEFVAL("")); ClassDB::bind_method(D_METHOD("parse_number", "number", "language"), &TextServer::parse_number, DEFVAL(""));
ClassDB::bind_method(D_METHOD("percent_sign", "language"), &TextServer::percent_sign, DEFVAL("")); ClassDB::bind_method(D_METHOD("percent_sign", "language"), &TextServer::percent_sign, DEFVAL(""));
#endif // DISABLE_DEPRECATED
ClassDB::bind_method(D_METHOD("string_get_word_breaks", "string", "language", "chars_per_line"), &TextServer::string_get_word_breaks, DEFVAL(""), DEFVAL(0)); ClassDB::bind_method(D_METHOD("string_get_word_breaks", "string", "language", "chars_per_line"), &TextServer::string_get_word_breaks, DEFVAL(""), DEFVAL(0));
ClassDB::bind_method(D_METHOD("string_get_character_breaks", "string", "language"), &TextServer::string_get_character_breaks, DEFVAL("")); ClassDB::bind_method(D_METHOD("string_get_character_breaks", "string", "language"), &TextServer::string_get_character_breaks, DEFVAL(""));
@ -2109,6 +2115,23 @@ String TextServer::strip_diacritics(const String &p_string) const {
return result; return result;
} }
#ifndef DISABLE_DEPRECATED
String TextServer::format_number(const String &p_string, const String &p_language) const {
const StringName lang = p_language.is_empty() ? TranslationServer::get_singleton()->get_tool_locale() : p_language;
return TranslationServer::get_singleton()->format_number(p_string, lang);
}
String TextServer::parse_number(const String &p_string, const String &p_language) const {
const StringName lang = p_language.is_empty() ? TranslationServer::get_singleton()->get_tool_locale() : p_language;
return TranslationServer::get_singleton()->parse_number(p_string, lang);
}
String TextServer::percent_sign(const String &p_language) const {
const StringName lang = p_language.is_empty() ? TranslationServer::get_singleton()->get_tool_locale() : p_language;
return TranslationServer::get_singleton()->get_percent_sign(lang);
}
#endif // DISABLE_DEPRECATED
TypedArray<Vector3i> TextServer::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const { TypedArray<Vector3i> TextServer::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
TypedArray<Vector3i> ret; TypedArray<Vector3i> ret;
switch (p_parser_type) { switch (p_parser_type) {

View file

@ -584,10 +584,12 @@ public:
void shaped_text_debug_print(const RID &p_shaped) const; void shaped_text_debug_print(const RID &p_shaped) const;
#endif #endif
#ifndef DISABLE_DEPRECATED
// Number conversion. // Number conversion.
virtual String format_number(const String &p_string, const String &p_language = "") const = 0; virtual String format_number(const String &p_string, const String &p_language = "") const;
virtual String parse_number(const String &p_string, const String &p_language = "") const = 0; virtual String parse_number(const String &p_string, const String &p_language = "") const;
virtual String percent_sign(const String &p_language = "") const = 0; virtual String percent_sign(const String &p_language = "") const;
#endif // DISABLE_DEPRECATED
// String functions. // String functions.
virtual PackedInt32Array string_get_word_breaks(const String &p_string, const String &p_language = "", int64_t p_chars_per_line = 0) const = 0; virtual PackedInt32Array string_get_word_breaks(const String &p_string, const String &p_language = "", int64_t p_chars_per_line = 0) const = 0;

View file

@ -365,9 +365,11 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(_shaped_text_prev_character_pos, "shaped", "pos"); GDVIRTUAL_BIND(_shaped_text_prev_character_pos, "shaped", "pos");
GDVIRTUAL_BIND(_shaped_text_closest_character_pos, "shaped", "pos"); GDVIRTUAL_BIND(_shaped_text_closest_character_pos, "shaped", "pos");
#ifndef DISABLE_DEPRECATED
GDVIRTUAL_BIND(_format_number, "number", "language"); GDVIRTUAL_BIND(_format_number, "number", "language");
GDVIRTUAL_BIND(_parse_number, "number", "language"); GDVIRTUAL_BIND(_parse_number, "number", "language");
GDVIRTUAL_BIND(_percent_sign, "language"); GDVIRTUAL_BIND(_percent_sign, "language");
#endif
GDVIRTUAL_BIND(_strip_diacritics, "string"); GDVIRTUAL_BIND(_strip_diacritics, "string");
GDVIRTUAL_BIND(_is_valid_identifier, "string"); GDVIRTUAL_BIND(_is_valid_identifier, "string");
@ -1652,12 +1654,13 @@ int64_t TextServerExtension::shaped_text_closest_character_pos(const RID &p_shap
return TextServer::shaped_text_closest_character_pos(p_shaped, p_pos); return TextServer::shaped_text_closest_character_pos(p_shaped, p_pos);
} }
#ifndef DISABLE_DEPRECATED
String TextServerExtension::format_number(const String &p_string, const String &p_language) const { String TextServerExtension::format_number(const String &p_string, const String &p_language) const {
String ret; String ret;
if (GDVIRTUAL_CALL(_format_number, p_string, p_language, ret)) { if (GDVIRTUAL_CALL(_format_number, p_string, p_language, ret)) {
return ret; return ret;
} }
return p_string; return TextServer::format_number(p_string, p_language);
} }
String TextServerExtension::parse_number(const String &p_string, const String &p_language) const { String TextServerExtension::parse_number(const String &p_string, const String &p_language) const {
@ -1665,14 +1668,17 @@ String TextServerExtension::parse_number(const String &p_string, const String &p
if (GDVIRTUAL_CALL(_parse_number, p_string, p_language, ret)) { if (GDVIRTUAL_CALL(_parse_number, p_string, p_language, ret)) {
return ret; return ret;
} }
return p_string; return TextServer::parse_number(p_string, p_language);
} }
String TextServerExtension::percent_sign(const String &p_language) const { String TextServerExtension::percent_sign(const String &p_language) const {
String ret = "%"; String ret = "%";
GDVIRTUAL_CALL(_percent_sign, p_language, ret); if (GDVIRTUAL_CALL(_percent_sign, p_language, ret)) {
return ret; return ret;
}
return TextServer::percent_sign(p_language);
} }
#endif // DISABLE_DEPRECATED
bool TextServerExtension::is_valid_identifier(const String &p_string) const { bool TextServerExtension::is_valid_identifier(const String &p_string) const {
bool ret; bool ret;

View file

@ -607,12 +607,14 @@ public:
GDVIRTUAL2RC(int64_t, _shaped_text_prev_character_pos, RID, int64_t); GDVIRTUAL2RC(int64_t, _shaped_text_prev_character_pos, RID, int64_t);
GDVIRTUAL2RC(int64_t, _shaped_text_closest_character_pos, RID, int64_t); GDVIRTUAL2RC(int64_t, _shaped_text_closest_character_pos, RID, int64_t);
#ifndef DISABLE_DEPRECATED
virtual String format_number(const String &p_string, const String &p_language = "") const override; virtual String format_number(const String &p_string, const String &p_language = "") const override;
virtual String parse_number(const String &p_string, const String &p_language = "") const override; virtual String parse_number(const String &p_string, const String &p_language = "") const override;
virtual String percent_sign(const String &p_language = "") const override; virtual String percent_sign(const String &p_language = "") const override;
GDVIRTUAL2RC(String, _format_number, const String &, const String &); GDVIRTUAL2RC(String, _format_number, const String &, const String &);
GDVIRTUAL2RC(String, _parse_number, const String &, const String &); GDVIRTUAL2RC(String, _parse_number, const String &, const String &);
GDVIRTUAL1RC(String, _percent_sign, const String &); GDVIRTUAL1RC(String, _percent_sign, const String &);
#endif // DISABLE_DEPRECATED
virtual String strip_diacritics(const String &p_string) const override; virtual String strip_diacritics(const String &p_string) const override;
GDVIRTUAL1RC(String, _strip_diacritics, const String &); GDVIRTUAL1RC(String, _strip_diacritics, const String &);