Add option to add built-in strings in the POT generation

This commit is contained in:
Michael Alexsander 2023-12-15 20:56:06 -03:00
parent df78c0636d
commit d70c45b5c8
No known key found for this signature in database
GPG Key ID: A9C91EE110F4EABA
23 changed files with 333 additions and 151 deletions

View File

@ -1514,6 +1514,7 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF_INTERNAL("internationalization/locale/translation_remaps", PackedStringArray());
GLOBAL_DEF_INTERNAL("internationalization/locale/translations", PackedStringArray());
GLOBAL_DEF_INTERNAL("internationalization/locale/translations_pot_files", PackedStringArray());
GLOBAL_DEF_INTERNAL("internationalization/locale/translation_add_builtin_strings_to_pot", false);
ProjectSettings::get_singleton()->add_hidden_prefix("input/");
}

View File

@ -1483,10 +1483,15 @@ String Object::tr(const StringName &p_message, const StringName &p_context) cons
}
if (Engine::get_singleton()->is_editor_hint()) {
String tr_msg = TranslationServer::get_singleton()->extractable_translate(p_message, p_context);
if (!tr_msg.is_empty()) {
return tr_msg;
}
return TranslationServer::get_singleton()->tool_translate(p_message, p_context);
} else {
return TranslationServer::get_singleton()->translate(p_message, p_context);
}
return TranslationServer::get_singleton()->translate(p_message, p_context);
}
String Object::tr_n(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context) const {
@ -1499,10 +1504,15 @@ String Object::tr_n(const StringName &p_message, const StringName &p_message_plu
}
if (Engine::get_singleton()->is_editor_hint()) {
String tr_msg = TranslationServer::get_singleton()->extractable_translate_plural(p_message, p_message_plural, p_n, p_context);
if (!tr_msg.is_empty()) {
return tr_msg;
}
return TranslationServer::get_singleton()->tool_translate_plural(p_message, p_message_plural, p_n, p_context);
} else {
return TranslationServer::get_singleton()->translate_plural(p_message, p_message_plural, p_n, p_context);
}
return TranslationServer::get_singleton()->translate_plural(p_message, p_message_plural, p_n, p_context);
}
void Object::_clear_internal_resource_paths(const Variant &p_var) {

View File

@ -772,6 +772,20 @@ StringName TranslationServer::tool_translate_plural(const StringName &p_message,
return p_message_plural;
}
void TranslationServer::set_property_translation(const Ref<Translation> &p_translation) {
property_translation = p_translation;
}
StringName TranslationServer::property_translate(const StringName &p_message) const {
if (property_translation.is_valid()) {
StringName r = property_translation->get_message(p_message);
if (r) {
return r;
}
}
return p_message;
}
void TranslationServer::set_doc_translation(const Ref<Translation> &p_translation) {
doc_translation = p_translation;
}
@ -800,13 +814,13 @@ StringName TranslationServer::doc_translate_plural(const StringName &p_message,
return p_message_plural;
}
void TranslationServer::set_property_translation(const Ref<Translation> &p_translation) {
property_translation = p_translation;
void TranslationServer::set_extractable_translation(const Ref<Translation> &p_translation) {
extractable_translation = p_translation;
}
StringName TranslationServer::property_translate(const StringName &p_message) const {
if (property_translation.is_valid()) {
StringName r = property_translation->get_message(p_message);
StringName TranslationServer::extractable_translate(const StringName &p_message, const StringName &p_context) const {
if (extractable_translation.is_valid()) {
StringName r = extractable_translation->get_message(p_message, p_context);
if (r) {
return r;
}
@ -814,6 +828,20 @@ StringName TranslationServer::property_translate(const StringName &p_message) co
return p_message;
}
StringName TranslationServer::extractable_translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context) const {
if (extractable_translation.is_valid()) {
StringName r = extractable_translation->get_plural_message(p_message, p_message_plural, p_n, p_context);
if (r) {
return r;
}
}
if (p_n == 1) {
return p_message;
}
return p_message_plural;
}
bool TranslationServer::is_pseudolocalization_enabled() const {
return pseudolocalization_enabled;
}

View File

@ -82,8 +82,9 @@ class TranslationServer : public Object {
HashSet<Ref<Translation>> translations;
Ref<Translation> tool_translation;
Ref<Translation> doc_translation;
Ref<Translation> property_translation;
Ref<Translation> doc_translation;
Ref<Translation> extractable_translation;
bool enabled = true;
@ -181,11 +182,14 @@ public:
Ref<Translation> get_tool_translation() const;
StringName tool_translate(const StringName &p_message, const StringName &p_context = "") const;
StringName tool_translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context = "") const;
void set_property_translation(const Ref<Translation> &p_translation);
StringName property_translate(const StringName &p_message) const;
void set_doc_translation(const Ref<Translation> &p_translation);
StringName doc_translate(const StringName &p_message, const StringName &p_context = "") const;
StringName doc_translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context = "") const;
void set_property_translation(const Ref<Translation> &p_translation);
StringName property_translate(const StringName &p_message) const;
void set_extractable_translation(const Ref<Translation> &p_translation);
StringName extractable_translate(const StringName &p_message, const StringName &p_context = "") const;
StringName extractable_translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context = "") const;
void setup();

View File

@ -5391,9 +5391,7 @@ String DTRN(const String &p_text, const String &p_text_plural, int p_n, const St
/**
* "Run-time TRanslate". Performs string replacement for internationalization
* within a running project. The translation string must be supplied by the
* project, as Godot does not provide built-in translations for `RTR()` strings
* to keep binary size low. A translation context can optionally be specified to
* without the editor. A translation context can optionally be specified to
* disambiguate between identical source strings in translations. When
* placeholders are desired, use `vformat(RTR("Example: %s"), some_string)`.
* If a string mentions a quantity (and may therefore need a dynamic plural form),
@ -5407,9 +5405,8 @@ String RTR(const String &p_text, const String &p_context) {
String rtr = TranslationServer::get_singleton()->tool_translate(p_text, p_context);
if (rtr.is_empty() || rtr == p_text) {
return TranslationServer::get_singleton()->translate(p_text, p_context);
} else {
return rtr;
}
return rtr;
}
return p_text;
@ -5417,13 +5414,10 @@ String RTR(const String &p_text, const String &p_context) {
/**
* "Run-time TRanslate for N items". Performs string replacement for
* internationalization within a running project. The translation string must be
* supplied by the project, as Godot does not provide built-in translations for
* `RTRN()` strings to keep binary size low. A translation context can
* optionally be specified to disambiguate between identical source strings in
* translations. Use `RTR()` if the string doesn't need dynamic plural form.
* When placeholders are desired, use
* `vformat(RTRN("%d item", "%d items", some_integer), some_integer)`.
* internationalization without the editor. A translation context can optionally
* be specified to disambiguate between identical source strings in translations.
* Use `RTR()` if the string doesn't need dynamic plural form. When placeholders
* are desired, use `vformat(RTRN("%d item", "%d items", some_integer), some_integer)`.
* The placeholder must be present in both strings to avoid run-time warnings in `vformat()`.
*
* NOTE: Do not use `RTRN()` in editor-only code (typically within the `editor/`
@ -5434,9 +5428,8 @@ String RTRN(const String &p_text, const String &p_text_plural, int p_n, const St
String rtr = TranslationServer::get_singleton()->tool_translate_plural(p_text, p_text_plural, p_n, p_context);
if (rtr.is_empty() || rtr == p_text || rtr == p_text_plural) {
return TranslationServer::get_singleton()->translate_plural(p_text, p_text_plural, p_n, p_context);
} else {
return rtr;
}
return rtr;
}
// Return message based on English plural rule if translation is not possible.

View File

@ -556,6 +556,43 @@ String DTRN(const String &p_text, const String &p_text_plural, int p_n, const St
String RTR(const String &p_text, const String &p_context = "");
String RTRN(const String &p_text, const String &p_text_plural, int p_n, const String &p_context = "");
/**
* "Extractable TRanslate". Used for strings that can appear inside an exported
* project (such as the ones in nodes like `FileDialog`), which are made possible
* to add in the POT generator. A translation context can optionally be specified
* to disambiguate between identical source strings in translations.
* When placeholders are desired, use vformat(ETR("Example: %s"), some_string)`.
* If a string mentions a quantity (and may therefore need a dynamic plural form),
* use `ETRN()` instead of `ETR()`.
*
* NOTE: This function is for string extraction only, and will just return the
* string it was given. The translation itself should be done internally by nodes
* with `atr()` instead.
*/
_FORCE_INLINE_ String ETR(const String &p_text, const String &p_context = "") {
return p_text;
}
/**
* "Extractable TRanslate for N items". Used for strings that can appear inside an
* exported project (such as the ones in nodes like `FileDialog`), which are made
* possible to add in the POT generator. A translation context can optionally be
* specified to disambiguate between identical source strings in translations.
* Use `ETR()` if the string doesn't need dynamic plural form. When placeholders
* are desired, use `vformat(ETRN("%d item", "%d items", some_integer), some_integer)`.
* The placeholder must be present in both strings to avoid run-time warnings in `vformat()`.
*
* NOTE: This function is for string extraction only, and will just return the
* string it was given. The translation itself should be done internally by nodes
* with `atr()` instead.
*/
_FORCE_INLINE_ String ETRN(const String &p_text, const String &p_text_plural, int p_n, const String &p_context = "") {
if (p_n == 1) {
return p_text;
}
return p_text_plural;
}
bool select_word(const String &p_s, int p_col, int &r_beg, int &r_end);
_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr) {

View File

@ -104,6 +104,15 @@ if env.editor_build:
env.Run(editor_builders.make_doc_translations_header, "Generating translations header."),
)
# Extractable translations
tlist = glob.glob(env.Dir("#editor/translations/extractable").abspath + "/*.po")
env.Depends("#editor/extractable_translations.gen.h", tlist)
env.CommandNoCache(
"#editor/extractable_translations.gen.h",
tlist,
env.Run(editor_builders.make_extractable_translations_header, "Generating extractable translations header."),
)
env.add_source_files(env.editor_sources, "*.cpp")
env.add_source_files(env.editor_sources, "register_exporters.gen.cpp")

View File

@ -140,5 +140,9 @@ def make_doc_translations_header(target, source, env):
make_translations_header(target, source, env, "doc")
def make_extractable_translations_header(target, source, env):
make_translations_header(target, source, env, "extractable")
if __name__ == "__main__":
subprocess_main(globals())

View File

@ -1060,6 +1060,9 @@ void EditorSettings::setup_language() {
// Load class reference translation.
load_doc_translations(lang);
// Load extractable translation for projects.
load_extractable_translations(lang);
}
void EditorSettings::setup_network() {

View File

@ -35,6 +35,7 @@
#include "core/io/translation_loader_po.h"
#include "editor/doc_translations.gen.h"
#include "editor/editor_translations.gen.h"
#include "editor/extractable_translations.gen.h"
#include "editor/property_translations.gen.h"
Vector<String> get_editor_locales() {
@ -77,6 +78,32 @@ void load_editor_translations(const String &p_locale) {
}
}
void load_property_translations(const String &p_locale) {
PropertyTranslationList *etl = _property_translations;
while (etl->data) {
if (etl->lang == p_locale) {
Vector<uint8_t> data;
data.resize(etl->uncomp_size);
int ret = Compression::decompress(data.ptrw(), etl->uncomp_size, etl->data, etl->comp_size, Compression::MODE_DEFLATE);
ERR_FAIL_COND_MSG(ret == -1, "Compressed file is corrupt.");
Ref<FileAccessMemory> fa;
fa.instantiate();
fa->open_custom(data.ptr(), data.size());
Ref<Translation> tr = TranslationLoaderPO::load_translation(fa);
if (tr.is_valid()) {
tr->set_locale(etl->lang);
TranslationServer::get_singleton()->set_property_translation(tr);
break;
}
}
etl++;
}
}
void load_doc_translations(const String &p_locale) {
DocTranslationList *dtl = _doc_translations;
while (dtl->data) {
@ -103,8 +130,8 @@ void load_doc_translations(const String &p_locale) {
}
}
void load_property_translations(const String &p_locale) {
PropertyTranslationList *etl = _property_translations;
void load_extractable_translations(const String &p_locale) {
ExtractableTranslationList *etl = _extractable_translations;
while (etl->data) {
if (etl->lang == p_locale) {
Vector<uint8_t> data;
@ -120,7 +147,7 @@ void load_property_translations(const String &p_locale) {
if (tr.is_valid()) {
tr->set_locale(etl->lang);
TranslationServer::get_singleton()->set_property_translation(tr);
TranslationServer::get_singleton()->set_extractable_translation(tr);
break;
}
}
@ -128,3 +155,29 @@ void load_property_translations(const String &p_locale) {
etl++;
}
}
List<StringName> get_extractable_message_list() {
ExtractableTranslationList *etl = _extractable_translations;
List<StringName> msgids;
while (etl->data) {
Vector<uint8_t> data;
data.resize(etl->uncomp_size);
int ret = Compression::decompress(data.ptrw(), etl->uncomp_size, etl->data, etl->comp_size, Compression::MODE_DEFLATE);
ERR_FAIL_COND_V_MSG(ret == -1, msgids, "Compressed file is corrupt.");
Ref<FileAccessMemory> fa;
fa.instantiate();
fa->open_custom(data.ptr(), data.size());
Ref<Translation> tr = TranslationLoaderPO::load_translation(fa);
if (tr.is_valid()) {
tr->get_message_list(&msgids);
break;
}
etl++;
}
return msgids;
}

View File

@ -32,11 +32,14 @@
#define EDITOR_TRANSLATION_H
#include "core/string/ustring.h"
#include "core/templates/list.h"
#include "core/templates/vector.h"
Vector<String> get_editor_locales();
void load_editor_translations(const String &p_locale);
void load_doc_translations(const String &p_locale);
void load_property_translations(const String &p_locale);
void load_doc_translations(const String &p_locale);
void load_extractable_translations(const String &p_locale);
List<StringName> get_extractable_message_list();
#endif // EDITOR_TRANSLATION_H

View File

@ -45,6 +45,7 @@ void LocalizationEditor::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
translation_list->connect("button_clicked", callable_mp(this, &LocalizationEditor::_translation_delete));
translation_pot_list->connect("button_clicked", callable_mp(this, &LocalizationEditor::_pot_delete));
translation_pot_add_builtin->set_pressed(GLOBAL_GET("internationalization/locale/translation_add_builtin_strings_to_pot"));
List<String> tfn;
ResourceLoader::get_recognized_extensions_for_type("Translation", &tfn);
@ -377,6 +378,11 @@ void LocalizationEditor::_pot_generate_open() {
pot_generate_dialog->popup_file_dialog();
}
void LocalizationEditor::_pot_add_builtin_toggled() {
ProjectSettings::get_singleton()->set_setting("internationalization/locale/translation_add_builtin_strings_to_pot", translation_pot_add_builtin->is_pressed());
ProjectSettings::get_singleton()->save();
}
void LocalizationEditor::_pot_generate(const String &p_file) {
POTGenerator::get_singleton()->generate_pot(p_file);
}
@ -730,13 +736,14 @@ LocalizationEditor::LocalizationEditor() {
pot_generate_button->connect("pressed", callable_mp(this, &LocalizationEditor::_pot_generate_open));
thb->add_child(pot_generate_button);
VBoxContainer *tmc = memnew(VBoxContainer);
tmc->set_v_size_flags(Control::SIZE_EXPAND_FILL);
tvb->add_child(tmc);
translation_pot_list = memnew(Tree);
translation_pot_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
tmc->add_child(translation_pot_list);
tvb->add_child(translation_pot_list);
translation_pot_add_builtin = memnew(CheckBox(TTR("Add Built-in Strings to POT")));
translation_pot_add_builtin->set_tooltip_text(TTR("Add strings from built-in components such as certain Control nodes."));
translation_pot_add_builtin->connect("pressed", callable_mp(this, &LocalizationEditor::_pot_add_builtin_toggled));
tvb->add_child(translation_pot_add_builtin);
pot_generate_dialog = memnew(EditorFileDialog);
pot_generate_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);

View File

@ -32,6 +32,7 @@
#define LOCALIZATION_EDITOR_H
#include "editor/editor_locale_dialog.h"
#include "scene/gui/check_box.h"
#include "scene/gui/tree.h"
class EditorFileDialog;
@ -52,6 +53,7 @@ class LocalizationEditor : public VBoxContainer {
Tree *translation_remap_options = nullptr;
Tree *translation_pot_list = nullptr;
CheckBox *translation_pot_add_builtin = nullptr;
EditorFileDialog *pot_file_open_dialog = nullptr;
EditorFileDialog *pot_generate_dialog = nullptr;
Button *pot_generate_button = nullptr;
@ -78,6 +80,7 @@ class LocalizationEditor : public VBoxContainer {
void _pot_delete(Object *p_item, int p_column, int p_button, MouseButton p_mouse_button);
void _pot_file_open();
void _pot_generate_open();
void _pot_add_builtin_toggled();
void _pot_generate(const String &p_file);
void _update_pot_file_extensions();

View File

@ -32,6 +32,7 @@
#include "core/config/project_settings.h"
#include "core/error/error_macros.h"
#include "editor/editor_translation.h"
#include "editor/editor_translation_parser.h"
#include "plugins/packed_scene_translation_parser_plugin.h"
@ -65,6 +66,8 @@ void POTGenerator::generate_pot(const String &p_file) {
// Clear all_translation_strings of the previous round.
all_translation_strings.clear();
List<StringName> extractable_msgids = get_extractable_message_list();
// Collect all translatable strings according to files order in "POT Generation" setting.
for (int i = 0; i < files.size(); i++) {
Vector<String> msgids;
@ -88,6 +91,12 @@ void POTGenerator::generate_pot(const String &p_file) {
}
}
if (GLOBAL_GET("internationalization/locale/translation_add_builtin_strings_to_pot")) {
for (int i = 0; i < extractable_msgids.size(); i++) {
_add_new_msgid(extractable_msgids[i], "", "", "");
}
}
_write_to_pot(p_file);
}
@ -136,7 +145,9 @@ void POTGenerator::_write_to_pot(const String &p_file) {
// Write file locations.
for (const String &E : locations) {
file->store_line("#: " + E.trim_prefix("res://").replace("\n", "\\n"));
if (!E.is_empty()) {
file->store_line("#: " + E.trim_prefix("res://").replace("\n", "\\n"));
}
}
// Write context.

View File

@ -1824,14 +1824,14 @@ void CodeEdit::create_code_region() {
}
int to_line = get_selection_to_line(caret_idx);
set_line(to_line, get_line(to_line) + "\n" + code_region_end_string);
insert_line_at(from_line, code_region_start_string + " " + RTR("New Code Region"));
insert_line_at(from_line, code_region_start_string + " " + atr(ETR("New Code Region")));
fold_line(from_line);
}
// Select name of the first region to allow quick edit.
remove_secondary_carets();
set_caret_line(first_region_start);
int tag_length = code_region_start_string.length() + RTR("New Code Region").length() + 1;
int tag_length = code_region_start_string.length() + atr(ETR("New Code Region")).length() + 1;
set_caret_column(tag_length);
select(first_region_start, code_region_start_string.length() + 1, first_region_start, tag_length);

View File

@ -54,6 +54,22 @@ void ColorPicker::_notification(int p_what) {
_update_color();
} break;
case NOTIFICATION_TRANSLATION_CHANGED: {
List<BaseButton *> buttons;
preset_group->get_buttons(&buttons);
for (List<BaseButton *>::Element *E = buttons.front(); E; E = E->next()) {
Color preset_color = ((ColorPresetButton *)E->get())->get_preset_color();
E->get()->set_tooltip_text(vformat(atr(ETR("Color: #%s\nLMB: Apply color\nRMB: Remove preset")), preset_color.to_html(preset_color.a < 1)));
}
buttons.clear();
recent_preset_group->get_buttons(&buttons);
for (List<BaseButton *>::Element *E = buttons.front(); E; E = E->next()) {
Color preset_color = ((ColorPresetButton *)E->get())->get_preset_color();
E->get()->set_tooltip_text(vformat(atr(ETR("Color: #%s\nLMB: Apply color")), preset_color.to_html(preset_color.a < 1)));
}
} break;
case NOTIFICATION_THEME_CHANGED: {
btn_pick->set_icon(theme_cache.screen_picker);
_update_drop_down_arrow(btn_preset->is_pressed(), btn_preset);
@ -689,7 +705,7 @@ void ColorPicker::_text_type_toggled() {
text_type->set_icon(nullptr);
c_text->set_editable(true);
c_text->set_tooltip_text(RTR("Enter a hex code (\"#ff0000\") or named color (\"red\")."));
c_text->set_tooltip_text(ETR("Enter a hex code (\"#ff0000\") or named color (\"red\")."));
}
_update_color();
}
@ -735,7 +751,7 @@ inline int ColorPicker::_get_preset_size() {
void ColorPicker::_add_preset_button(int p_size, const Color &p_color) {
ColorPresetButton *btn_preset_new = memnew(ColorPresetButton(p_color, p_size));
btn_preset_new->set_tooltip_text(vformat(RTR("Color: #%s\nLMB: Apply color\nRMB: Remove preset"), p_color.to_html(p_color.a < 1)));
btn_preset_new->set_tooltip_text(vformat(atr(ETR("Color: #%s\nLMB: Apply color\nRMB: Remove preset")), p_color.to_html(p_color.a < 1)));
SET_DRAG_FORWARDING_GCDU(btn_preset_new, ColorPicker);
btn_preset_new->set_button_group(preset_group);
preset_container->add_child(btn_preset_new);
@ -745,7 +761,7 @@ void ColorPicker::_add_preset_button(int p_size, const Color &p_color) {
void ColorPicker::_add_recent_preset_button(int p_size, const Color &p_color) {
ColorPresetButton *btn_preset_new = memnew(ColorPresetButton(p_color, p_size));
btn_preset_new->set_tooltip_text(vformat(RTR("Color: #%s\nLMB: Apply color"), p_color.to_html(p_color.a < 1)));
btn_preset_new->set_tooltip_text(vformat(atr(ETR("Color: #%s\nLMB: Apply color")), p_color.to_html(p_color.a < 1)));
btn_preset_new->set_button_group(recent_preset_group);
recent_preset_hbc->add_child(btn_preset_new);
recent_preset_hbc->move_child(btn_preset_new, 0);
@ -1807,11 +1823,11 @@ ColorPicker::ColorPicker() {
btn_pick = memnew(Button);
sample_hbc->add_child(btn_pick);
if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_SCREEN_CAPTURE)) {
btn_pick->set_tooltip_text(RTR("Pick a color from the screen."));
btn_pick->set_tooltip_text(ETR("Pick a color from the screen."));
btn_pick->connect(SNAME("pressed"), callable_mp(this, &ColorPicker::_pick_button_pressed));
} else {
// On unsupported platforms, use a legacy method for color picking.
btn_pick->set_tooltip_text(RTR("Pick a color from the application window."));
btn_pick->set_tooltip_text(ETR("Pick a color from the application window."));
btn_pick->connect(SNAME("pressed"), callable_mp(this, &ColorPicker::_pick_button_pressed_legacy));
}
@ -1825,7 +1841,7 @@ ColorPicker::ColorPicker() {
btn_shape->set_flat(false);
sample_hbc->add_child(btn_shape);
btn_shape->set_toggle_mode(true);
btn_shape->set_tooltip_text(RTR("Select a picker shape."));
btn_shape->set_tooltip_text(ETR("Select a picker shape."));
current_shape = SHAPE_HSV_RECTANGLE;
@ -1864,7 +1880,7 @@ ColorPicker::ColorPicker() {
btn_mode->set_flat(false);
mode_hbc->add_child(btn_mode);
btn_mode->set_toggle_mode(true);
btn_mode->set_tooltip_text(RTR("Select a picker mode."));
btn_mode->set_tooltip_text(ETR("Select a picker mode."));
current_mode = MODE_RGB;
@ -1918,8 +1934,8 @@ ColorPicker::ColorPicker() {
hex_hbc->add_child(c_text);
c_text->set_h_size_flags(SIZE_EXPAND_FILL);
c_text->set_select_all_on_focus(true);
c_text->set_tooltip_text(RTR("Enter a hex code (\"#ff0000\") or named color (\"red\")."));
c_text->set_placeholder(RTR("Hex code or named color"));
c_text->set_tooltip_text(ETR("Enter a hex code (\"#ff0000\") or named color (\"red\")."));
c_text->set_placeholder(ETR("Hex code or named color"));
c_text->connect("text_submitted", callable_mp(this, &ColorPicker::_html_submitted));
c_text->connect("text_changed", callable_mp(this, &ColorPicker::_text_changed));
c_text->connect("focus_exited", callable_mp(this, &ColorPicker::_html_focus_exit));
@ -1997,7 +2013,7 @@ ColorPicker::ColorPicker() {
btn_add_preset = memnew(Button);
btn_add_preset->set_icon_alignment(HORIZONTAL_ALIGNMENT_CENTER);
btn_add_preset->set_tooltip_text(RTR("Add current color as a preset."));
btn_add_preset->set_tooltip_text(ETR("Add current color as a preset."));
btn_add_preset->connect("pressed", callable_mp(this, &ColorPicker::_add_preset_pressed));
preset_container->add_child(btn_add_preset);
}

View File

@ -302,7 +302,7 @@ void FileDialog::update_dir() {
if (drives->is_visible()) {
if (dir_access->get_current_dir().is_network_share_path()) {
_update_drives(false);
drives->add_item(RTR("Network"));
drives->add_item(ETR("Network"));
drives->set_item_disabled(-1, true);
drives->select(drives->get_item_count() - 1);
} else {
@ -459,7 +459,7 @@ void FileDialog::_action_pressed() {
}
if (dir_access->file_exists(f)) {
confirm_save->set_text(vformat(RTR("File \"%s\" already exists.\nDo you want to overwrite it?"), f));
confirm_save->set_text(vformat(atr(ETR("File \"%s\" already exists.\nDo you want to overwrite it?")), f));
confirm_save->popup_centered(Size2(250, 80));
} else {
emit_signal(SNAME("file_selected"), f);
@ -539,10 +539,10 @@ void FileDialog::deselect_all() {
switch (mode) {
case FILE_MODE_OPEN_FILE:
case FILE_MODE_OPEN_FILES:
set_ok_button_text(RTR("Open"));
set_ok_button_text(ETR("Open"));
break;
case FILE_MODE_OPEN_DIR:
set_ok_button_text(RTR("Select Current Folder"));
set_ok_button_text(ETR("Select Current Folder"));
break;
case FILE_MODE_OPEN_ANY:
case FILE_MODE_SAVE_FILE:
@ -566,7 +566,7 @@ void FileDialog::_tree_selected() {
if (!d["dir"]) {
file->set_text(d["name"]);
} else if (mode == FILE_MODE_OPEN_DIR) {
set_ok_button_text(RTR("Select This Folder"));
set_ok_button_text(ETR("Select This Folder"));
}
get_ok_button()->set_disabled(_is_open_should_be_disabled());
@ -621,7 +621,7 @@ void FileDialog::update_file_list() {
if (dir_access->is_readable(dir_access->get_current_dir().utf8().get_data())) {
message->hide();
} else {
message->set_text(RTR("You don't have permission to access contents of this folder."));
message->set_text(ETR("You don't have permission to access contents of this folder."));
message->show();
}
@ -771,7 +771,7 @@ void FileDialog::update_filters() {
all_filters += ", ...";
}
filter->add_item(RTR("All Recognized") + " (" + all_filters + ")");
filter->add_item(atr(ETR("All Recognized")) + " (" + all_filters + ")");
}
for (int i = 0; i < filters.size(); i++) {
String flt = filters[i].get_slice(";", 0).strip_edges();
@ -783,7 +783,7 @@ void FileDialog::update_filters() {
}
}
filter->add_item(RTR("All Files") + " (*)");
filter->add_item(atr(ETR("All Files")) + " (*)");
}
void FileDialog::clear_filters() {
@ -896,37 +896,37 @@ void FileDialog::set_file_mode(FileMode p_mode) {
mode = p_mode;
switch (mode) {
case FILE_MODE_OPEN_FILE:
set_ok_button_text(RTR("Open"));
set_ok_button_text(ETR("Open"));
if (mode_overrides_title) {
set_title(TTRC("Open a File"));
set_title(ETR("Open a File"));
}
makedir->hide();
break;
case FILE_MODE_OPEN_FILES:
set_ok_button_text(RTR("Open"));
set_ok_button_text(ETR("Open"));
if (mode_overrides_title) {
set_title(TTRC("Open File(s)"));
set_title(ETR("Open File(s)"));
}
makedir->hide();
break;
case FILE_MODE_OPEN_DIR:
set_ok_button_text(RTR("Select Current Folder"));
set_ok_button_text(ETR("Select Current Folder"));
if (mode_overrides_title) {
set_title(TTRC("Open a Directory"));
set_title(ETR("Open a Directory"));
}
makedir->show();
break;
case FILE_MODE_OPEN_ANY:
set_ok_button_text(RTR("Open"));
set_ok_button_text(ETR("Open"));
if (mode_overrides_title) {
set_title(TTRC("Open a File or Directory"));
set_title(ETR("Open a File or Directory"));
}
makedir->show();
break;
case FILE_MODE_SAVE_FILE:
set_ok_button_text(RTR("Save"));
set_ok_button_text(ETR("Save"));
if (mode_overrides_title) {
set_title(TTRC("Save a File"));
set_title(ETR("Save a File"));
}
makedir->show();
break;
@ -1389,13 +1389,13 @@ FileDialog::FileDialog() {
dir_prev = memnew(Button);
dir_prev->set_theme_type_variation("FlatButton");
dir_prev->set_tooltip_text(RTR("Go to previous folder."));
dir_prev->set_tooltip_text(ETR("Go to previous folder."));
dir_next = memnew(Button);
dir_next->set_theme_type_variation("FlatButton");
dir_next->set_tooltip_text(RTR("Go to next folder."));
dir_next->set_tooltip_text(ETR("Go to next folder."));
dir_up = memnew(Button);
dir_up->set_theme_type_variation("FlatButton");
dir_up->set_tooltip_text(RTR("Go to parent folder."));
dir_up->set_tooltip_text(ETR("Go to parent folder."));
hbc->add_child(dir_prev);
hbc->add_child(dir_next);
hbc->add_child(dir_up);
@ -1403,7 +1403,7 @@ FileDialog::FileDialog() {
dir_next->connect("pressed", callable_mp(this, &FileDialog::_go_forward));
dir_up->connect("pressed", callable_mp(this, &FileDialog::_go_up));
hbc->add_child(memnew(Label(RTR("Path:"))));
hbc->add_child(memnew(Label(ETR("Path:"))));
drives_container = memnew(HBoxContainer);
hbc->add_child(drives_container);
@ -1419,7 +1419,7 @@ FileDialog::FileDialog() {
refresh = memnew(Button);
refresh->set_theme_type_variation("FlatButton");
refresh->set_tooltip_text(RTR("Refresh files."));
refresh->set_tooltip_text(ETR("Refresh files."));
refresh->connect("pressed", callable_mp(this, &FileDialog::update_file_list));
hbc->add_child(refresh);
@ -1427,7 +1427,7 @@ FileDialog::FileDialog() {
show_hidden->set_theme_type_variation("FlatButton");
show_hidden->set_toggle_mode(true);
show_hidden->set_pressed(is_showing_hidden_files());
show_hidden->set_tooltip_text(RTR("Toggle the visibility of hidden files."));
show_hidden->set_tooltip_text(ETR("Toggle the visibility of hidden files."));
show_hidden->connect("toggled", callable_mp(this, &FileDialog::set_show_hidden_files));
hbc->add_child(show_hidden);
@ -1436,14 +1436,14 @@ FileDialog::FileDialog() {
makedir = memnew(Button);
makedir->set_theme_type_variation("FlatButton");
makedir->set_tooltip_text(RTR("Create a new folder."));
makedir->set_tooltip_text(ETR("Create a new folder."));
makedir->connect("pressed", callable_mp(this, &FileDialog::_make_dir));
hbc->add_child(makedir);
vbox->add_child(hbc);
tree = memnew(Tree);
tree->set_hide_root(true);
vbox->add_margin_child(RTR("Directories & Files:"), tree, true);
vbox->add_margin_child(ETR("Directories & Files:"), tree, true);
message = memnew(Label);
message->hide();
@ -1453,7 +1453,7 @@ FileDialog::FileDialog() {
tree->add_child(message);
file_box = memnew(HBoxContainer);
file_box->add_child(memnew(Label(RTR("File:"))));
file_box->add_child(memnew(Label(ETR("File:"))));
file = memnew(LineEdit);
file->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE);
file->set_stretch_ratio(4);
@ -1489,22 +1489,22 @@ FileDialog::FileDialog() {
confirm_save->connect("confirmed", callable_mp(this, &FileDialog::_save_confirm_pressed));
makedialog = memnew(ConfirmationDialog);
makedialog->set_title(RTR("Create Folder"));
makedialog->set_title(ETR("Create Folder"));
VBoxContainer *makevb = memnew(VBoxContainer);
makedialog->add_child(makevb);
makedirname = memnew(LineEdit);
makedirname->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE);
makevb->add_margin_child(RTR("Name:"), makedirname);
makevb->add_margin_child(ETR("Name:"), makedirname);
add_child(makedialog, false, INTERNAL_MODE_FRONT);
makedialog->register_text_enter(makedirname);
makedialog->connect("confirmed", callable_mp(this, &FileDialog::_make_dir_confirm));
mkdirerr = memnew(AcceptDialog);
mkdirerr->set_text(RTR("Could not create folder."));
mkdirerr->set_text(ETR("Could not create folder."));
add_child(mkdirerr, false, INTERNAL_MODE_FRONT);
exterr = memnew(AcceptDialog);
exterr->set_text(RTR("Invalid extension, or empty filename."));
exterr->set_text(ETR("Invalid extension, or empty filename."));
add_child(exterr, false, INTERNAL_MODE_FRONT);
update_filters();

View File

@ -2435,7 +2435,7 @@ GraphEdit::GraphEdit() {
zoom_minus_button = memnew(Button);
zoom_minus_button->set_theme_type_variation("FlatButton");
zoom_minus_button->set_visible(show_zoom_buttons);
zoom_minus_button->set_tooltip_text(RTR("Zoom Out"));
zoom_minus_button->set_tooltip_text(ETR("Zoom Out"));
zoom_minus_button->set_focus_mode(FOCUS_NONE);
menu_hbox->add_child(zoom_minus_button);
zoom_minus_button->connect("pressed", callable_mp(this, &GraphEdit::_zoom_minus));
@ -2443,7 +2443,7 @@ GraphEdit::GraphEdit() {
zoom_reset_button = memnew(Button);
zoom_reset_button->set_theme_type_variation("FlatButton");
zoom_reset_button->set_visible(show_zoom_buttons);
zoom_reset_button->set_tooltip_text(RTR("Zoom Reset"));
zoom_reset_button->set_tooltip_text(ETR("Zoom Reset"));
zoom_reset_button->set_focus_mode(FOCUS_NONE);
menu_hbox->add_child(zoom_reset_button);
zoom_reset_button->connect("pressed", callable_mp(this, &GraphEdit::_zoom_reset));
@ -2451,7 +2451,7 @@ GraphEdit::GraphEdit() {
zoom_plus_button = memnew(Button);
zoom_plus_button->set_theme_type_variation("FlatButton");
zoom_plus_button->set_visible(show_zoom_buttons);
zoom_plus_button->set_tooltip_text(RTR("Zoom In"));
zoom_plus_button->set_tooltip_text(ETR("Zoom In"));
zoom_plus_button->set_focus_mode(FOCUS_NONE);
menu_hbox->add_child(zoom_plus_button);
zoom_plus_button->connect("pressed", callable_mp(this, &GraphEdit::_zoom_plus));
@ -2463,7 +2463,7 @@ GraphEdit::GraphEdit() {
toggle_grid_button->set_visible(show_grid_buttons);
toggle_grid_button->set_toggle_mode(true);
toggle_grid_button->set_pressed(true);
toggle_grid_button->set_tooltip_text(RTR("Toggle the visual grid."));
toggle_grid_button->set_tooltip_text(ETR("Toggle the visual grid."));
toggle_grid_button->set_focus_mode(FOCUS_NONE);
menu_hbox->add_child(toggle_grid_button);
toggle_grid_button->connect("pressed", callable_mp(this, &GraphEdit::_show_grid_toggled));
@ -2472,7 +2472,7 @@ GraphEdit::GraphEdit() {
toggle_snapping_button->set_theme_type_variation("FlatButton");
toggle_snapping_button->set_visible(show_grid_buttons);
toggle_snapping_button->set_toggle_mode(true);
toggle_snapping_button->set_tooltip_text(RTR("Toggle snapping to the grid."));
toggle_snapping_button->set_tooltip_text(ETR("Toggle snapping to the grid."));
toggle_snapping_button->set_pressed(snapping_enabled);
toggle_snapping_button->set_focus_mode(FOCUS_NONE);
menu_hbox->add_child(toggle_snapping_button);
@ -2484,7 +2484,7 @@ GraphEdit::GraphEdit() {
snapping_distance_spinbox->set_max(GRID_MAX_SNAPPING_DISTANCE);
snapping_distance_spinbox->set_step(1);
snapping_distance_spinbox->set_value(snapping_distance);
snapping_distance_spinbox->set_tooltip_text(RTR("Change the snapping distance."));
snapping_distance_spinbox->set_tooltip_text(ETR("Change the snapping distance."));
menu_hbox->add_child(snapping_distance_spinbox);
snapping_distance_spinbox->connect("value_changed", callable_mp(this, &GraphEdit::_snapping_distance_changed));
@ -2494,7 +2494,7 @@ GraphEdit::GraphEdit() {
minimap_button->set_theme_type_variation("FlatButton");
minimap_button->set_visible(show_minimap_button);
minimap_button->set_toggle_mode(true);
minimap_button->set_tooltip_text(RTR("Toggle the graph minimap."));
minimap_button->set_tooltip_text(ETR("Toggle the graph minimap."));
minimap_button->set_pressed(show_grid);
minimap_button->set_focus_mode(FOCUS_NONE);
menu_hbox->add_child(minimap_button);
@ -2506,7 +2506,7 @@ GraphEdit::GraphEdit() {
arrange_button->connect("pressed", callable_mp(this, &GraphEdit::arrange_nodes));
arrange_button->set_focus_mode(FOCUS_NONE);
menu_hbox->add_child(arrange_button);
arrange_button->set_tooltip_text(RTR("Automatically arrange selected nodes."));
arrange_button->set_tooltip_text(ETR("Automatically arrange selected nodes."));
// Minimap.

View File

@ -2406,45 +2406,45 @@ void LineEdit::_generate_context_menu() {
add_child(menu, false, INTERNAL_MODE_FRONT);
menu_dir = memnew(PopupMenu);
menu_dir->add_radio_check_item(RTR("Same as Layout Direction"), MENU_DIR_INHERITED);
menu_dir->add_radio_check_item(RTR("Auto-Detect Direction"), MENU_DIR_AUTO);
menu_dir->add_radio_check_item(RTR("Left-to-Right"), MENU_DIR_LTR);
menu_dir->add_radio_check_item(RTR("Right-to-Left"), MENU_DIR_RTL);
menu_dir->add_radio_check_item(ETR("Same as Layout Direction"), MENU_DIR_INHERITED);
menu_dir->add_radio_check_item(ETR("Auto-Detect Direction"), MENU_DIR_AUTO);
menu_dir->add_radio_check_item(ETR("Left-to-Right"), MENU_DIR_LTR);
menu_dir->add_radio_check_item(ETR("Right-to-Left"), MENU_DIR_RTL);
menu_ctl = memnew(PopupMenu);
menu_ctl->add_item(RTR("Left-to-Right Mark (LRM)"), MENU_INSERT_LRM);
menu_ctl->add_item(RTR("Right-to-Left Mark (RLM)"), MENU_INSERT_RLM);
menu_ctl->add_item(RTR("Start of Left-to-Right Embedding (LRE)"), MENU_INSERT_LRE);
menu_ctl->add_item(RTR("Start of Right-to-Left Embedding (RLE)"), MENU_INSERT_RLE);
menu_ctl->add_item(RTR("Start of Left-to-Right Override (LRO)"), MENU_INSERT_LRO);
menu_ctl->add_item(RTR("Start of Right-to-Left Override (RLO)"), MENU_INSERT_RLO);
menu_ctl->add_item(RTR("Pop Direction Formatting (PDF)"), MENU_INSERT_PDF);
menu_ctl->add_item(ETR("Left-to-Right Mark (LRM)"), MENU_INSERT_LRM);
menu_ctl->add_item(ETR("Right-to-Left Mark (RLM)"), MENU_INSERT_RLM);
menu_ctl->add_item(ETR("Start of Left-to-Right Embedding (LRE)"), MENU_INSERT_LRE);
menu_ctl->add_item(ETR("Start of Right-to-Left Embedding (RLE)"), MENU_INSERT_RLE);
menu_ctl->add_item(ETR("Start of Left-to-Right Override (LRO)"), MENU_INSERT_LRO);
menu_ctl->add_item(ETR("Start of Right-to-Left Override (RLO)"), MENU_INSERT_RLO);
menu_ctl->add_item(ETR("Pop Direction Formatting (PDF)"), MENU_INSERT_PDF);
menu_ctl->add_separator();
menu_ctl->add_item(RTR("Arabic Letter Mark (ALM)"), MENU_INSERT_ALM);
menu_ctl->add_item(RTR("Left-to-Right Isolate (LRI)"), MENU_INSERT_LRI);
menu_ctl->add_item(RTR("Right-to-Left Isolate (RLI)"), MENU_INSERT_RLI);
menu_ctl->add_item(RTR("First Strong Isolate (FSI)"), MENU_INSERT_FSI);
menu_ctl->add_item(RTR("Pop Direction Isolate (PDI)"), MENU_INSERT_PDI);
menu_ctl->add_item(ETR("Arabic Letter Mark (ALM)"), MENU_INSERT_ALM);
menu_ctl->add_item(ETR("Left-to-Right Isolate (LRI)"), MENU_INSERT_LRI);
menu_ctl->add_item(ETR("Right-to-Left Isolate (RLI)"), MENU_INSERT_RLI);
menu_ctl->add_item(ETR("First Strong Isolate (FSI)"), MENU_INSERT_FSI);
menu_ctl->add_item(ETR("Pop Direction Isolate (PDI)"), MENU_INSERT_PDI);
menu_ctl->add_separator();
menu_ctl->add_item(RTR("Zero-Width Joiner (ZWJ)"), MENU_INSERT_ZWJ);
menu_ctl->add_item(RTR("Zero-Width Non-Joiner (ZWNJ)"), MENU_INSERT_ZWNJ);
menu_ctl->add_item(RTR("Word Joiner (WJ)"), MENU_INSERT_WJ);
menu_ctl->add_item(RTR("Soft Hyphen (SHY)"), MENU_INSERT_SHY);
menu_ctl->add_item(ETR("Zero-Width Joiner (ZWJ)"), MENU_INSERT_ZWJ);
menu_ctl->add_item(ETR("Zero-Width Non-Joiner (ZWNJ)"), MENU_INSERT_ZWNJ);
menu_ctl->add_item(ETR("Word Joiner (WJ)"), MENU_INSERT_WJ);
menu_ctl->add_item(ETR("Soft Hyphen (SHY)"), MENU_INSERT_SHY);
menu->add_item(RTR("Cut"), MENU_CUT);
menu->add_item(RTR("Copy"), MENU_COPY);
menu->add_item(RTR("Paste"), MENU_PASTE);
menu->add_item(ETR("Cut"), MENU_CUT);
menu->add_item(ETR("Copy"), MENU_COPY);
menu->add_item(ETR("Paste"), MENU_PASTE);
menu->add_separator();
menu->add_item(RTR("Select All"), MENU_SELECT_ALL);
menu->add_item(RTR("Clear"), MENU_CLEAR);
menu->add_item(ETR("Select All"), MENU_SELECT_ALL);
menu->add_item(ETR("Clear"), MENU_CLEAR);
menu->add_separator();
menu->add_item(RTR("Undo"), MENU_UNDO);
menu->add_item(RTR("Redo"), MENU_REDO);
menu->add_item(ETR("Undo"), MENU_UNDO);
menu->add_item(ETR("Redo"), MENU_REDO);
menu->add_separator();
menu->add_submenu_node_item(RTR("Text Writing Direction"), menu_dir, MENU_SUBMENU_TEXT_DIR);
menu->add_submenu_node_item(ETR("Text Writing Direction"), menu_dir, MENU_SUBMENU_TEXT_DIR);
menu->add_separator();
menu->add_check_item(RTR("Display Control Characters"), MENU_DISPLAY_UCC);
menu->add_submenu_node_item(RTR("Insert Control Character"), menu_ctl, MENU_SUBMENU_INSERT_UCC);
menu->add_check_item(ETR("Display Control Characters"), MENU_DISPLAY_UCC);
menu->add_submenu_node_item(ETR("Insert Control Character"), menu_ctl, MENU_SUBMENU_INSERT_UCC);
menu->connect("id_pressed", callable_mp(this, &LineEdit::menu_option));
menu_dir->connect("id_pressed", callable_mp(this, &LineEdit::menu_option));

View File

@ -6270,8 +6270,8 @@ void RichTextLabel::_generate_context_menu() {
add_child(menu, false, INTERNAL_MODE_FRONT);
menu->connect("id_pressed", callable_mp(this, &RichTextLabel::menu_option));
menu->add_item(RTR("Copy"), MENU_COPY);
menu->add_item(RTR("Select All"), MENU_SELECT_ALL);
menu->add_item(ETR("Copy"), MENU_COPY);
menu->add_item(ETR("Select All"), MENU_SELECT_ALL);
}
void RichTextLabel::_update_context_menu() {

View File

@ -6873,45 +6873,45 @@ void TextEdit::_generate_context_menu() {
add_child(menu, false, INTERNAL_MODE_FRONT);
menu_dir = memnew(PopupMenu);
menu_dir->add_radio_check_item(RTR("Same as Layout Direction"), MENU_DIR_INHERITED);
menu_dir->add_radio_check_item(RTR("Auto-Detect Direction"), MENU_DIR_AUTO);
menu_dir->add_radio_check_item(RTR("Left-to-Right"), MENU_DIR_LTR);
menu_dir->add_radio_check_item(RTR("Right-to-Left"), MENU_DIR_RTL);
menu_dir->add_radio_check_item(ETR("Same as Layout Direction"), MENU_DIR_INHERITED);
menu_dir->add_radio_check_item(ETR("Auto-Detect Direction"), MENU_DIR_AUTO);
menu_dir->add_radio_check_item(ETR("Left-to-Right"), MENU_DIR_LTR);
menu_dir->add_radio_check_item(ETR("Right-to-Left"), MENU_DIR_RTL);
menu_ctl = memnew(PopupMenu);
menu_ctl->add_item(RTR("Left-to-Right Mark (LRM)"), MENU_INSERT_LRM);
menu_ctl->add_item(RTR("Right-to-Left Mark (RLM)"), MENU_INSERT_RLM);
menu_ctl->add_item(RTR("Start of Left-to-Right Embedding (LRE)"), MENU_INSERT_LRE);
menu_ctl->add_item(RTR("Start of Right-to-Left Embedding (RLE)"), MENU_INSERT_RLE);
menu_ctl->add_item(RTR("Start of Left-to-Right Override (LRO)"), MENU_INSERT_LRO);
menu_ctl->add_item(RTR("Start of Right-to-Left Override (RLO)"), MENU_INSERT_RLO);
menu_ctl->add_item(RTR("Pop Direction Formatting (PDF)"), MENU_INSERT_PDF);
menu_ctl->add_item(ETR("Left-to-Right Mark (LRM)"), MENU_INSERT_LRM);
menu_ctl->add_item(ETR("Right-to-Left Mark (RLM)"), MENU_INSERT_RLM);
menu_ctl->add_item(ETR("Start of Left-to-Right Embedding (LRE)"), MENU_INSERT_LRE);
menu_ctl->add_item(ETR("Start of Right-to-Left Embedding (RLE)"), MENU_INSERT_RLE);
menu_ctl->add_item(ETR("Start of Left-to-Right Override (LRO)"), MENU_INSERT_LRO);
menu_ctl->add_item(ETR("Start of Right-to-Left Override (RLO)"), MENU_INSERT_RLO);
menu_ctl->add_item(ETR("Pop Direction Formatting (PDF)"), MENU_INSERT_PDF);
menu_ctl->add_separator();
menu_ctl->add_item(RTR("Arabic Letter Mark (ALM)"), MENU_INSERT_ALM);
menu_ctl->add_item(RTR("Left-to-Right Isolate (LRI)"), MENU_INSERT_LRI);
menu_ctl->add_item(RTR("Right-to-Left Isolate (RLI)"), MENU_INSERT_RLI);
menu_ctl->add_item(RTR("First Strong Isolate (FSI)"), MENU_INSERT_FSI);
menu_ctl->add_item(RTR("Pop Direction Isolate (PDI)"), MENU_INSERT_PDI);
menu_ctl->add_item(ETR("Arabic Letter Mark (ALM)"), MENU_INSERT_ALM);
menu_ctl->add_item(ETR("Left-to-Right Isolate (LRI)"), MENU_INSERT_LRI);
menu_ctl->add_item(ETR("Right-to-Left Isolate (RLI)"), MENU_INSERT_RLI);
menu_ctl->add_item(ETR("First Strong Isolate (FSI)"), MENU_INSERT_FSI);
menu_ctl->add_item(ETR("Pop Direction Isolate (PDI)"), MENU_INSERT_PDI);
menu_ctl->add_separator();
menu_ctl->add_item(RTR("Zero-Width Joiner (ZWJ)"), MENU_INSERT_ZWJ);
menu_ctl->add_item(RTR("Zero-Width Non-Joiner (ZWNJ)"), MENU_INSERT_ZWNJ);
menu_ctl->add_item(RTR("Word Joiner (WJ)"), MENU_INSERT_WJ);
menu_ctl->add_item(RTR("Soft Hyphen (SHY)"), MENU_INSERT_SHY);
menu_ctl->add_item(ETR("Zero-Width Joiner (ZWJ)"), MENU_INSERT_ZWJ);
menu_ctl->add_item(ETR("Zero-Width Non-Joiner (ZWNJ)"), MENU_INSERT_ZWNJ);
menu_ctl->add_item(ETR("Word Joiner (WJ)"), MENU_INSERT_WJ);
menu_ctl->add_item(ETR("Soft Hyphen (SHY)"), MENU_INSERT_SHY);
menu->add_item(RTR("Cut"), MENU_CUT);
menu->add_item(RTR("Copy"), MENU_COPY);
menu->add_item(RTR("Paste"), MENU_PASTE);
menu->add_item(ETR("Cut"), MENU_CUT);
menu->add_item(ETR("Copy"), MENU_COPY);
menu->add_item(ETR("Paste"), MENU_PASTE);
menu->add_separator();
menu->add_item(RTR("Select All"), MENU_SELECT_ALL);
menu->add_item(RTR("Clear"), MENU_CLEAR);
menu->add_item(ETR("Select All"), MENU_SELECT_ALL);
menu->add_item(ETR("Clear"), MENU_CLEAR);
menu->add_separator();
menu->add_item(RTR("Undo"), MENU_UNDO);
menu->add_item(RTR("Redo"), MENU_REDO);
menu->add_item(ETR("Undo"), MENU_UNDO);
menu->add_item(ETR("Redo"), MENU_REDO);
menu->add_separator();
menu->add_submenu_node_item(RTR("Text Writing Direction"), menu_dir, MENU_SUBMENU_TEXT_DIR);
menu->add_submenu_node_item(ETR("Text Writing Direction"), menu_dir, MENU_SUBMENU_TEXT_DIR);
menu->add_separator();
menu->add_check_item(RTR("Display Control Characters"), MENU_DISPLAY_UCC);
menu->add_submenu_node_item(RTR("Insert Control Character"), menu_ctl, MENU_SUBMENU_INSERT_UCC);
menu->add_check_item(ETR("Display Control Characters"), MENU_DISPLAY_UCC);
menu->add_submenu_node_item(ETR("Insert Control Character"), menu_ctl, MENU_SUBMENU_INSERT_UCC);
menu->connect("id_pressed", callable_mp(this, &TextEdit::menu_option));
menu_dir->connect("id_pressed", callable_mp(this, &TextEdit::menu_option));

View File

@ -1949,7 +1949,7 @@ void Tree::update_item_cell(TreeItem *p_item, int p_col) {
int option = (int)p_item->cells[p_col].val;
valtext = RTR("(Other)");
valtext = atr(ETR("(Other)"));
Vector<String> strings = p_item->cells[p_col].text.split(",");
for (int j = 0; j < strings.size(); j++) {
int value = j;

View File

@ -1447,7 +1447,7 @@ String Viewport::_gui_get_tooltip(Control *p_control, const Vector2 &p_pos, Cont
String tooltip;
while (p_control) {
tooltip = p_control->get_tooltip(pos);
tooltip = p_control->atr(p_control->get_tooltip(pos));
// Temporary solution for PopupMenus.
PopupMenu *menu = Object::cast_to<PopupMenu>(this);