diff options
author | Rémi Verschelde <remi@verschelde.fr> | 2022-01-18 15:43:04 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-18 15:43:04 +0100 |
commit | ce2b5bdfa893f339078b7d2179b2541dcc71dca1 (patch) | |
tree | 54220f27ad3237e0dee00ec4ae6d8ee0c9dc7339 /editor | |
parent | 28cd81c581365d15ee2cc497d48164de498a7208 (diff) | |
parent | 40c56ed410e828d2062de7e4ba5617b3e1c0f631 (diff) |
Merge pull request #52969 from bruvzg/locale_detection
Diffstat (limited to 'editor')
-rw-r--r-- | editor/editor_locale_dialog.cpp | 563 | ||||
-rw-r--r-- | editor/editor_locale_dialog.h | 93 | ||||
-rw-r--r-- | editor/editor_properties.cpp | 62 | ||||
-rw-r--r-- | editor/editor_properties.h | 21 | ||||
-rw-r--r-- | editor/editor_settings.cpp | 16 | ||||
-rw-r--r-- | editor/import/dynamicfont_import_settings.cpp | 425 | ||||
-rw-r--r-- | editor/import/dynamicfont_import_settings.h | 7 | ||||
-rw-r--r-- | editor/import/resource_importer_csv_translation.cpp | 3 | ||||
-rw-r--r-- | editor/localization_editor.cpp | 251 | ||||
-rw-r--r-- | editor/localization_editor.h | 17 | ||||
-rw-r--r-- | editor/property_editor.cpp | 25 | ||||
-rw-r--r-- | editor/property_editor.h | 3 |
12 files changed, 823 insertions, 663 deletions
diff --git a/editor/editor_locale_dialog.cpp b/editor/editor_locale_dialog.cpp new file mode 100644 index 0000000000..5c4ece7065 --- /dev/null +++ b/editor/editor_locale_dialog.cpp @@ -0,0 +1,563 @@ +/*************************************************************************/ +/* editor_locale_dialog.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "editor_locale_dialog.h" + +#include "editor/editor_node.h" +#include "editor/editor_scale.h" +#include "scene/gui/check_button.h" +#include "scene/gui/line_edit.h" +#include "scene/gui/option_button.h" +#include "scene/gui/tree.h" + +static _FORCE_INLINE_ bool is_upper_case(char32_t c) { + return (c >= 'A' && c <= 'Z'); +} + +static _FORCE_INLINE_ bool is_lower_case(char32_t c) { + return (c >= 'a' && c <= 'z'); +} + +void EditorLocaleDialog::_bind_methods() { + ADD_SIGNAL(MethodInfo("locale_selected", PropertyInfo(Variant::STRING, "locale"))); +} + +void EditorLocaleDialog::ok_pressed() { + if (edit_filters->is_pressed()) { + return; // Do not update, if in filter edit mode. + } + + String locale; + if (lang_code->get_text().is_empty()) { + return; // Language code is required. + } + locale = lang_code->get_text(); + + if (!script_code->get_text().is_empty()) { + locale += "_" + script_code->get_text(); + } + if (!country_code->get_text().is_empty()) { + locale += "_" + country_code->get_text(); + } + if (!variant_code->get_text().is_empty()) { + locale += "_" + variant_code->get_text(); + } + + emit_signal(SNAME("locale_selected"), TranslationServer::get_singleton()->standardize_locale(locale)); + hide(); +} + +void EditorLocaleDialog::_item_selected() { + if (updating_lists) { + return; + } + + if (edit_filters->is_pressed()) { + return; // Do not update, if in filter edit mode. + } + + TreeItem *l = lang_list->get_selected(); + if (l) { + lang_code->set_text(l->get_metadata(0).operator String()); + } + + TreeItem *s = script_list->get_selected(); + if (s) { + script_code->set_text(s->get_metadata(0).operator String()); + } + + TreeItem *c = cnt_list->get_selected(); + if (c) { + country_code->set_text(c->get_metadata(0).operator String()); + } +} + +void EditorLocaleDialog::_toggle_advanced(bool p_checked) { + if (!p_checked) { + script_code->set_text(""); + variant_code->set_text(""); + } + _update_tree(); +} + +void EditorLocaleDialog::_post_popup() { + ConfirmationDialog::_post_popup(); + + if (!locale_set) { + lang_code->set_text(""); + script_code->set_text(""); + country_code->set_text(""); + variant_code->set_text(""); + } + edit_filters->set_pressed(false); + _update_tree(); +} + +void EditorLocaleDialog::_filter_lang_option_changed() { + TreeItem *t = lang_list->get_edited(); + String lang = t->get_metadata(0); + bool checked = t->is_checked(0); + + Variant prev; + Array f_lang_all; + + if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/language_filter")) { + f_lang_all = ProjectSettings::get_singleton()->get("internationalization/locale/language_filter"); + prev = f_lang_all; + } + + int l_idx = f_lang_all.find(lang); + + if (checked) { + if (l_idx == -1) { + f_lang_all.append(lang); + } + } else { + if (l_idx != -1) { + f_lang_all.remove_at(l_idx); + } + } + + f_lang_all.sort(); + + undo_redo->create_action(TTR("Changed Locale Language Filter")); + undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/language_filter", f_lang_all); + undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/language_filter", prev); + undo_redo->commit_action(); +} + +void EditorLocaleDialog::_filter_script_option_changed() { + TreeItem *t = script_list->get_edited(); + String script = t->get_metadata(0); + bool checked = t->is_checked(0); + + Variant prev; + Array f_script_all; + + if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/script_filter")) { + f_script_all = ProjectSettings::get_singleton()->get("internationalization/locale/script_filter"); + prev = f_script_all; + } + + int l_idx = f_script_all.find(script); + + if (checked) { + if (l_idx == -1) { + f_script_all.append(script); + } + } else { + if (l_idx != -1) { + f_script_all.remove_at(l_idx); + } + } + + f_script_all.sort(); + + undo_redo->create_action(TTR("Changed Locale Script Filter")); + undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/script_filter", f_script_all); + undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/script_filter", prev); + undo_redo->commit_action(); +} + +void EditorLocaleDialog::_filter_cnt_option_changed() { + TreeItem *t = cnt_list->get_edited(); + String cnt = t->get_metadata(0); + bool checked = t->is_checked(0); + + Variant prev; + Array f_cnt_all; + + if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/country_filter")) { + f_cnt_all = ProjectSettings::get_singleton()->get("internationalization/locale/country_filter"); + prev = f_cnt_all; + } + + int l_idx = f_cnt_all.find(cnt); + + if (checked) { + if (l_idx == -1) { + f_cnt_all.append(cnt); + } + } else { + if (l_idx != -1) { + f_cnt_all.remove_at(l_idx); + } + } + + f_cnt_all.sort(); + + undo_redo->create_action(TTR("Changed Locale Country Filter")); + undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/country_filter", f_cnt_all); + undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/country_filter", prev); + undo_redo->commit_action(); +} + +void EditorLocaleDialog::_filter_mode_changed(int p_mode) { + int f_mode = filter_mode->get_selected_id(); + Variant prev; + + if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/locale_filter_mode")) { + prev = ProjectSettings::get_singleton()->get("internationalization/locale/locale_filter_mode"); + } + + undo_redo->create_action(TTR("Changed Locale Filter Mode")); + undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/locale_filter_mode", f_mode); + undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/locale_filter_mode", prev); + undo_redo->commit_action(); + + _update_tree(); +} + +void EditorLocaleDialog::_edit_filters(bool p_checked) { + _update_tree(); +} + +void EditorLocaleDialog::_update_tree() { + updating_lists = true; + + int filter = SHOW_ALL_LOCALES; + if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/locale_filter_mode")) { + filter = ProjectSettings::get_singleton()->get("internationalization/locale/locale_filter_mode"); + } + Array f_lang_all; + if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/language_filter")) { + f_lang_all = ProjectSettings::get_singleton()->get("internationalization/locale/language_filter"); + } + Array f_cnt_all; + if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/country_filter")) { + f_cnt_all = ProjectSettings::get_singleton()->get("internationalization/locale/country_filter"); + } + Array f_script_all; + if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/script_filter")) { + f_script_all = ProjectSettings::get_singleton()->get("internationalization/locale/script_filter"); + } + bool is_edit_mode = edit_filters->is_pressed(); + + filter_mode->select(filter); + + // Hide text advanced edit and disable OK button if in filter edit mode. + advanced->set_visible(!is_edit_mode); + hb_locale->set_visible(!is_edit_mode && advanced->is_pressed()); + vb_script_list->set_visible(advanced->is_pressed()); + get_ok_button()->set_disabled(is_edit_mode); + + // Update language list. + lang_list->clear(); + TreeItem *l_root = lang_list->create_item(nullptr); + lang_list->set_hide_root(true); + + Vector<String> languages = TranslationServer::get_singleton()->get_all_languages(); + for (const String &E : languages) { + if (is_edit_mode || (filter == SHOW_ALL_LOCALES) || f_lang_all.has(E) || f_lang_all.is_empty()) { + const String &lang = TranslationServer::get_singleton()->get_language_name(E); + TreeItem *t = lang_list->create_item(l_root); + if (is_edit_mode) { + t->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); + t->set_editable(0, true); + t->set_checked(0, f_lang_all.has(E)); + } else if (lang_code->get_text() == E) { + t->select(0); + } + t->set_text(0, vformat("%s [%s]", lang, E)); + t->set_metadata(0, E); + } + } + + // Update script list. + script_list->clear(); + TreeItem *s_root = script_list->create_item(nullptr); + script_list->set_hide_root(true); + + if (!is_edit_mode) { + TreeItem *t = script_list->create_item(s_root); + t->set_text(0, "[Default]"); + t->set_metadata(0, ""); + } + + Vector<String> scripts = TranslationServer::get_singleton()->get_all_scripts(); + for (const String &E : scripts) { + if (is_edit_mode || (filter == SHOW_ALL_LOCALES) || f_script_all.has(E) || f_script_all.is_empty()) { + const String &script = TranslationServer::get_singleton()->get_script_name(E); + TreeItem *t = script_list->create_item(s_root); + if (is_edit_mode) { + t->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); + t->set_editable(0, true); + t->set_checked(0, f_script_all.has(E)); + } else if (script_code->get_text() == E) { + t->select(0); + } + t->set_text(0, vformat("%s [%s]", script, E)); + t->set_metadata(0, E); + } + } + + // Update country list. + cnt_list->clear(); + TreeItem *c_root = cnt_list->create_item(nullptr); + cnt_list->set_hide_root(true); + + if (!is_edit_mode) { + TreeItem *t = cnt_list->create_item(c_root); + t->set_text(0, "[Default]"); + t->set_metadata(0, ""); + } + + Vector<String> countries = TranslationServer::get_singleton()->get_all_countries(); + for (const String &E : countries) { + if (is_edit_mode || (filter == SHOW_ALL_LOCALES) || f_cnt_all.has(E) || f_cnt_all.is_empty()) { + const String &cnt = TranslationServer::get_singleton()->get_country_name(E); + TreeItem *t = cnt_list->create_item(c_root); + if (is_edit_mode) { + t->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); + t->set_editable(0, true); + t->set_checked(0, f_cnt_all.has(E)); + } else if (country_code->get_text() == E) { + t->select(0); + } + t->set_text(0, vformat("%s [%s]", cnt, E)); + t->set_metadata(0, E); + } + } + updating_lists = false; +} + +void EditorLocaleDialog::set_locale(const String &p_locale) { + const String &locale = TranslationServer::get_singleton()->standardize_locale(p_locale); + if (locale.is_empty()) { + locale_set = false; + + lang_code->set_text(""); + script_code->set_text(""); + country_code->set_text(""); + variant_code->set_text(""); + } else { + locale_set = true; + + Vector<String> locale_elements = p_locale.split("_"); + lang_code->set_text(locale_elements[0]); + if (locale_elements.size() >= 2) { + if (locale_elements[1].length() == 4 && is_upper_case(locale_elements[1][0]) && is_lower_case(locale_elements[1][1]) && is_lower_case(locale_elements[1][2]) && is_lower_case(locale_elements[1][3])) { + script_code->set_text(locale_elements[1]); + advanced->set_pressed(true); + } + if (locale_elements[1].length() == 2 && is_upper_case(locale_elements[1][0]) && is_upper_case(locale_elements[1][1])) { + country_code->set_text(locale_elements[1]); + } + } + if (locale_elements.size() >= 3) { + if (locale_elements[2].length() == 2 && is_upper_case(locale_elements[2][0]) && is_upper_case(locale_elements[2][1])) { + country_code->set_text(locale_elements[2]); + } else { + variant_code->set_text(locale_elements[2].to_lower()); + advanced->set_pressed(true); + } + } + if (locale_elements.size() >= 4) { + variant_code->set_text(locale_elements[3].to_lower()); + advanced->set_pressed(true); + } + } +} + +void EditorLocaleDialog::popup_locale_dialog() { + popup_centered_clamped(Size2(1050, 700) * EDSCALE, 0.8); +} + +EditorLocaleDialog::EditorLocaleDialog() { + undo_redo = EditorNode::get_undo_redo(); + + set_title(TTR("Select a Locale")); + + VBoxContainer *vb = memnew(VBoxContainer); + { + HBoxContainer *hb_filter = memnew(HBoxContainer); + { + filter_mode = memnew(OptionButton); + filter_mode->add_item(TTR("Show All Locales"), SHOW_ALL_LOCALES); + filter_mode->set_h_size_flags(Control::SIZE_EXPAND_FILL); + filter_mode->add_item(TTR("Show Selected Locales Only"), SHOW_ONLY_SELECTED_LOCALES); + filter_mode->select(0); + filter_mode->connect("item_selected", callable_mp(this, &EditorLocaleDialog::_filter_mode_changed)); + hb_filter->add_child(filter_mode); + } + { + edit_filters = memnew(CheckButton); + edit_filters->set_text("Edit Filters"); + edit_filters->set_toggle_mode(true); + edit_filters->set_pressed(false); + edit_filters->connect("toggled", callable_mp(this, &EditorLocaleDialog::_edit_filters)); + hb_filter->add_child(edit_filters); + } + { + advanced = memnew(CheckButton); + advanced->set_text("Advanced"); + advanced->set_toggle_mode(true); + advanced->set_pressed(false); + advanced->connect("toggled", callable_mp(this, &EditorLocaleDialog::_toggle_advanced)); + hb_filter->add_child(advanced); + } + vb->add_child(hb_filter); + } + { + HBoxContainer *hb_lists = memnew(HBoxContainer); + hb_lists->set_v_size_flags(Control::SIZE_EXPAND_FILL); + { + VBoxContainer *vb_lang_list = memnew(VBoxContainer); + vb_lang_list->set_h_size_flags(Control::SIZE_EXPAND_FILL); + { + Label *lang_lbl = memnew(Label); + lang_lbl->set_text(TTR("Language:")); + vb_lang_list->add_child(lang_lbl); + } + { + lang_list = memnew(Tree); + lang_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); + lang_list->connect("cell_selected", callable_mp(this, &EditorLocaleDialog::_item_selected)); + lang_list->set_columns(1); + lang_list->connect("item_edited", callable_mp(this, &EditorLocaleDialog::_filter_lang_option_changed)); + vb_lang_list->add_child(lang_list); + } + hb_lists->add_child(vb_lang_list); + } + { + vb_script_list = memnew(VBoxContainer); + vb_script_list->set_h_size_flags(Control::SIZE_EXPAND_FILL); + { + Label *script_lbl = memnew(Label); + script_lbl->set_text(TTR("Script:")); + vb_script_list->add_child(script_lbl); + } + { + script_list = memnew(Tree); + script_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); + script_list->connect("cell_selected", callable_mp(this, &EditorLocaleDialog::_item_selected)); + script_list->set_columns(1); + script_list->connect("item_edited", callable_mp(this, &EditorLocaleDialog::_filter_script_option_changed)); + vb_script_list->add_child(script_list); + } + hb_lists->add_child(vb_script_list); + } + { + VBoxContainer *vb_cnt_list = memnew(VBoxContainer); + vb_cnt_list->set_h_size_flags(Control::SIZE_EXPAND_FILL); + { + Label *cnt_lbl = memnew(Label); + cnt_lbl->set_text(TTR("Country:")); + vb_cnt_list->add_child(cnt_lbl); + } + { + cnt_list = memnew(Tree); + cnt_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); + cnt_list->connect("cell_selected", callable_mp(this, &EditorLocaleDialog::_item_selected)); + cnt_list->set_columns(1); + cnt_list->connect("item_edited", callable_mp(this, &EditorLocaleDialog::_filter_cnt_option_changed)); + vb_cnt_list->add_child(cnt_list); + } + hb_lists->add_child(vb_cnt_list); + } + vb->add_child(hb_lists); + } + { + hb_locale = memnew(HBoxContainer); + hb_locale->set_h_size_flags(Control::SIZE_EXPAND_FILL); + { + { + VBoxContainer *vb_language = memnew(VBoxContainer); + vb_language->set_h_size_flags(Control::SIZE_EXPAND_FILL); + { + Label *language_lbl = memnew(Label); + language_lbl->set_text(TTR("Language")); + vb_language->add_child(language_lbl); + } + { + lang_code = memnew(LineEdit); + lang_code->set_max_length(3); + lang_code->set_tooltip("Language"); + vb_language->add_child(lang_code); + } + hb_locale->add_child(vb_language); + } + { + VBoxContainer *vb_script = memnew(VBoxContainer); + vb_script->set_h_size_flags(Control::SIZE_EXPAND_FILL); + { + Label *script_lbl = memnew(Label); + script_lbl->set_text(TTR("Script")); + vb_script->add_child(script_lbl); + } + { + script_code = memnew(LineEdit); + script_code->set_max_length(4); + script_code->set_tooltip("Script"); + vb_script->add_child(script_code); + } + hb_locale->add_child(vb_script); + } + { + VBoxContainer *vb_country = memnew(VBoxContainer); + vb_country->set_h_size_flags(Control::SIZE_EXPAND_FILL); + { + Label *country_lbl = memnew(Label); + country_lbl->set_text(TTR("Country")); + vb_country->add_child(country_lbl); + } + { + country_code = memnew(LineEdit); + country_code->set_max_length(2); + country_code->set_tooltip("Country"); + vb_country->add_child(country_code); + } + hb_locale->add_child(vb_country); + } + { + VBoxContainer *vb_variant = memnew(VBoxContainer); + vb_variant->set_h_size_flags(Control::SIZE_EXPAND_FILL); + { + Label *variant_lbl = memnew(Label); + variant_lbl->set_text(TTR("Variant")); + vb_variant->add_child(variant_lbl); + } + { + variant_code = memnew(LineEdit); + variant_code->set_h_size_flags(Control::SIZE_EXPAND_FILL); + variant_code->set_placeholder("Variant"); + variant_code->set_tooltip("Variant"); + vb_variant->add_child(variant_code); + } + hb_locale->add_child(vb_variant); + } + } + vb->add_child(hb_locale); + } + add_child(vb); + _update_tree(); + + get_ok_button()->set_text(TTR("Select")); +} diff --git a/editor/editor_locale_dialog.h b/editor/editor_locale_dialog.h new file mode 100644 index 0000000000..7a4828e83a --- /dev/null +++ b/editor/editor_locale_dialog.h @@ -0,0 +1,93 @@ +/*************************************************************************/ +/* editor_locale_dialog.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef EDITOR_LOCALE_DIALOG_H +#define EDITOR_LOCALE_DIALOG_H + +#include "core/string/translation.h" +#include "scene/gui/dialogs.h" + +class Button; +class HBoxContainer; +class VBoxContainer; +class LineEdit; +class Tree; +class OptionButton; +class UndoRedo; + +class EditorLocaleDialog : public ConfirmationDialog { + GDCLASS(EditorLocaleDialog, ConfirmationDialog); + + enum LocaleFilter { + SHOW_ALL_LOCALES, + SHOW_ONLY_SELECTED_LOCALES, + }; + + HBoxContainer *hb_locale = nullptr; + VBoxContainer *vb_script_list = nullptr; + OptionButton *filter_mode = nullptr; + Button *edit_filters = nullptr; + Button *advanced = nullptr; + LineEdit *lang_code = nullptr; + LineEdit *script_code = nullptr; + LineEdit *country_code = nullptr; + LineEdit *variant_code = nullptr; + Tree *lang_list = nullptr; + Tree *script_list = nullptr; + Tree *cnt_list = nullptr; + + UndoRedo *undo_redo = nullptr; + + bool locale_set = false; + bool updating_lists = false; + +protected: + static void _bind_methods(); + virtual void _post_popup() override; + virtual void ok_pressed() override; + + void _item_selected(); + void _filter_lang_option_changed(); + void _filter_script_option_changed(); + void _filter_cnt_option_changed(); + void _filter_mode_changed(int p_mode); + void _edit_filters(bool p_checked); + void _toggle_advanced(bool p_checked); + + void _update_tree(); + +public: + EditorLocaleDialog(); + + void set_locale(const String &p_locale); + void popup_locale_dialog(); +}; + +#endif // EDITOR_LOCALE_DIALOG_H diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 97a38b9200..6bb4b5e81b 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -343,6 +343,64 @@ EditorPropertyTextEnum::EditorPropertyTextEnum() { add_focusable(cancel_button); } +//////////////////// LOCALE //////////////////////// + +void EditorPropertyLocale::_locale_selected(const String &p_locale) { + emit_changed(get_edited_property(), p_locale); + update_property(); +} + +void EditorPropertyLocale::_locale_pressed() { + if (!dialog) { + dialog = memnew(EditorLocaleDialog); + dialog->connect("locale_selected", callable_mp(this, &EditorPropertyLocale::_locale_selected)); + add_child(dialog); + } + + String locale_code = get_edited_object()->get(get_edited_property()); + dialog->set_locale(locale_code); + dialog->popup_locale_dialog(); +} + +void EditorPropertyLocale::update_property() { + String locale_code = get_edited_object()->get(get_edited_property()); + locale->set_text(locale_code); + locale->set_tooltip(locale_code); +} + +void EditorPropertyLocale::setup(const String &p_hint_text) { +} + +void EditorPropertyLocale::_notification(int p_what) { + if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { + locale_edit->set_icon(get_theme_icon(SNAME("Translation"), SNAME("EditorIcons"))); + } +} + +void EditorPropertyLocale::_locale_focus_exited() { + _locale_selected(locale->get_text()); +} + +void EditorPropertyLocale::_bind_methods() { +} + +EditorPropertyLocale::EditorPropertyLocale() { + HBoxContainer *locale_hb = memnew(HBoxContainer); + add_child(locale_hb); + locale = memnew(LineEdit); + locale_hb->add_child(locale); + locale->connect("text_submitted", callable_mp(this, &EditorPropertyLocale::_locale_selected)); + locale->connect("focus_exited", callable_mp(this, &EditorPropertyLocale::_locale_focus_exited)); + locale->set_h_size_flags(SIZE_EXPAND_FILL); + + locale_edit = memnew(Button); + locale_edit->set_clip_text(true); + locale_hb->add_child(locale_edit); + add_focusable(locale); + dialog = nullptr; + locale_edit->connect("pressed", callable_mp(this, &EditorPropertyLocale::_locale_pressed)); +} + ///////////////////// PATH ///////////////////////// void EditorPropertyPath::_set_read_only(bool p_read_only) { @@ -3379,6 +3437,10 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ EditorPropertyClassName *editor = memnew(EditorPropertyClassName); editor->setup("Object", p_hint_text); return editor; + } else if (p_hint == PROPERTY_HINT_LOCALE_ID) { + EditorPropertyLocale *editor = memnew(EditorPropertyLocale); + editor->setup(p_hint_text); + return editor; } else if (p_hint == PROPERTY_HINT_DIR || p_hint == PROPERTY_HINT_FILE || p_hint == PROPERTY_HINT_SAVE_FILE || p_hint == PROPERTY_HINT_GLOBAL_DIR || p_hint == PROPERTY_HINT_GLOBAL_FILE) { Vector<String> extensions = p_hint_text.split(","); bool global = p_hint == PROPERTY_HINT_GLOBAL_DIR || p_hint == PROPERTY_HINT_GLOBAL_FILE; diff --git a/editor/editor_properties.h b/editor/editor_properties.h index e62f6823a3..fdb0360d6b 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -33,6 +33,7 @@ #include "editor/create_dialog.h" #include "editor/editor_inspector.h" +#include "editor/editor_locale_dialog.h" #include "editor/editor_resource_picker.h" #include "editor/editor_spin_slider.h" #include "editor/property_selector.h" @@ -153,6 +154,26 @@ public: EditorPropertyPath(); }; +class EditorPropertyLocale : public EditorProperty { + GDCLASS(EditorPropertyLocale, EditorProperty); + EditorLocaleDialog *dialog; + LineEdit *locale; + Button *locale_edit; + + void _locale_selected(const String &p_locale); + void _locale_pressed(); + void _locale_focus_exited(); + +protected: + static void _bind_methods(); + void _notification(int p_what); + +public: + void setup(const String &p_hit_string); + virtual void update_property() override; + EditorPropertyLocale(); +}; + class EditorPropertyClassName : public EditorProperty { GDCLASS(EditorPropertyClassName, EditorProperty); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index b662eb8b1c..b9291bcd0f 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -339,7 +339,6 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { { String lang_hint = "en"; String host_lang = OS::get_singleton()->get_locale(); - host_lang = TranslationServer::standardize_locale(host_lang); // Skip locales if Text server lack required features. Vector<String> locales_to_skip; @@ -365,6 +364,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { } String best; + int best_score = 0; for (const String &locale : get_editor_locales()) { // Skip locales which we can't render properly (see above comment). // Test against language code without regional variants (e.g. ur_PK). @@ -376,16 +376,16 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { lang_hint += ","; lang_hint += locale; - if (host_lang == locale) { - best = locale; - } - - if (best.is_empty() && host_lang.begins_with(locale)) { + int score = TranslationServer::get_singleton()->compare_locales(host_lang, locale); + if (score >= best_score) { best = locale; + best_score = score; + if (score == 10) { + break; // Exact match, skip the rest. + } } } - - if (best.is_empty()) { + if (best_score == 0) { best = "en"; } diff --git a/editor/import/dynamicfont_import_settings.cpp b/editor/import/dynamicfont_import_settings.cpp index 3151496bec..f4b1468314 100644 --- a/editor/import/dynamicfont_import_settings.cpp +++ b/editor/import/dynamicfont_import_settings.cpp @@ -442,398 +442,6 @@ void DynamicFontImportSettings::_add_glyph_range_item(int32_t p_start, int32_t p } /*************************************************************************/ -/* Languages and scripts */ -/*************************************************************************/ - -struct CodeInfo { - String name; - String code; -}; - -static CodeInfo langs[] = { - { U"Custom", U"xx" }, - { U"-", U"-" }, - { U"Abkhazian", U"ab" }, - { U"Afar", U"aa" }, - { U"Afrikaans", U"af" }, - { U"Akan", U"ak" }, - { U"Albanian", U"sq" }, - { U"Amharic", U"am" }, - { U"Arabic", U"ar" }, - { U"Aragonese", U"an" }, - { U"Armenian", U"hy" }, - { U"Assamese", U"as" }, - { U"Avaric", U"av" }, - { U"Avestan", U"ae" }, - { U"Aymara", U"ay" }, - { U"Azerbaijani", U"az" }, - { U"Bambara", U"bm" }, - { U"Bashkir", U"ba" }, - { U"Basque", U"eu" }, - { U"Belarusian", U"be" }, - { U"Bengali", U"bn" }, - { U"Bihari", U"bh" }, - { U"Bislama", U"bi" }, - { U"Bosnian", U"bs" }, - { U"Breton", U"br" }, - { U"Bulgarian", U"bg" }, - { U"Burmese", U"my" }, - { U"Catalan", U"ca" }, - { U"Chamorro", U"ch" }, - { U"Chechen", U"ce" }, - { U"Chichewa", U"ny" }, - { U"Chinese", U"zh" }, - { U"Chuvash", U"cv" }, - { U"Cornish", U"kw" }, - { U"Corsican", U"co" }, - { U"Cree", U"cr" }, - { U"Croatian", U"hr" }, - { U"Czech", U"cs" }, - { U"Danish", U"da" }, - { U"Divehi", U"dv" }, - { U"Dutch", U"nl" }, - { U"Dzongkha", U"dz" }, - { U"English", U"en" }, - { U"Esperanto", U"eo" }, - { U"Estonian", U"et" }, - { U"Ewe", U"ee" }, - { U"Faroese", U"fo" }, - { U"Fijian", U"fj" }, - { U"Finnish", U"fi" }, - { U"French", U"fr" }, - { U"Fulah", U"ff" }, - { U"Galician", U"gl" }, - { U"Georgian", U"ka" }, - { U"German", U"de" }, - { U"Greek", U"el" }, - { U"Guarani", U"gn" }, - { U"Gujarati", U"gu" }, - { U"Haitian", U"ht" }, - { U"Hausa", U"ha" }, - { U"Hebrew", U"he" }, - { U"Herero", U"hz" }, - { U"Hindi", U"hi" }, - { U"Hiri Motu", U"ho" }, - { U"Hungarian", U"hu" }, - { U"Interlingua", U"ia" }, - { U"Indonesian", U"id" }, - { U"Interlingue", U"ie" }, - { U"Irish", U"ga" }, - { U"Igbo", U"ig" }, - { U"Inupiaq", U"ik" }, - { U"Ido", U"io" }, - { U"Icelandic", U"is" }, - { U"Italian", U"it" }, - { U"Inuktitut", U"iu" }, - { U"Japanese", U"ja" }, - { U"Javanese", U"jv" }, - { U"Kalaallisut", U"kl" }, - { U"Kannada", U"kn" }, - { U"Kanuri", U"kr" }, - { U"Kashmiri", U"ks" }, - { U"Kazakh", U"kk" }, - { U"Central Khmer", U"km" }, - { U"Kikuyu", U"ki" }, - { U"Kinyarwanda", U"rw" }, - { U"Kirghiz", U"ky" }, - { U"Komi", U"kv" }, - { U"Kongo", U"kg" }, - { U"Korean", U"ko" }, - { U"Kurdish", U"ku" }, - { U"Kuanyama", U"kj" }, - { U"Latin", U"la" }, - { U"Luxembourgish", U"lb" }, - { U"Ganda", U"lg" }, - { U"Limburgan", U"li" }, - { U"Lingala", U"ln" }, - { U"Lao", U"lo" }, - { U"Lithuanian", U"lt" }, - { U"Luba-Katanga", U"lu" }, - { U"Latvian", U"lv" }, - { U"Man", U"gv" }, - { U"Macedonian", U"mk" }, - { U"Malagasy", U"mg" }, - { U"Malay", U"ms" }, - { U"Malayalam", U"ml" }, - { U"Maltese", U"mt" }, - { U"Maori", U"mi" }, - { U"Marathi", U"mr" }, - { U"Marshallese", U"mh" }, - { U"Mongolian", U"mn" }, - { U"Nauru", U"na" }, - { U"Navajo", U"nv" }, - { U"North Ndebele", U"nd" }, - { U"Nepali", U"ne" }, - { U"Ndonga", U"ng" }, - { U"Norwegian Bokmål", U"nb" }, - { U"Norwegian Nynorsk", U"nn" }, - { U"Norwegian", U"no" }, - { U"Sichuan Yi, Nuosu", U"ii" }, - { U"South Ndebele", U"nr" }, - { U"Occitan", U"oc" }, - { U"Ojibwa", U"oj" }, - { U"Church Slavic", U"cu" }, - { U"Oromo", U"om" }, - { U"Oriya", U"or" }, - { U"Ossetian", U"os" }, - { U"Punjabi", U"pa" }, - { U"Pali", U"pi" }, - { U"Persian", U"fa" }, - { U"Polish", U"pl" }, - { U"Pashto", U"ps" }, - { U"Portuguese", U"pt" }, - { U"Quechua", U"qu" }, - { U"Romansh", U"rm" }, - { U"Rundi", U"rn" }, - { U"Romanian", U"ro" }, - { U"Russian", U"ru" }, - { U"Sanskrit", U"sa" }, - { U"Sardinian", U"sc" }, - { U"Sindhi", U"sd" }, - { U"Northern Sami", U"se" }, - { U"Samoan", U"sm" }, - { U"Sango", U"sg" }, - { U"Serbian", U"sr" }, - { U"Gaelic", U"gd" }, - { U"Shona", U"sn" }, - { U"Sinhala", U"si" }, - { U"Slovak", U"sk" }, - { U"Slovenian", U"sl" }, - { U"Somali", U"so" }, - { U"Southern Sotho", U"st" }, - { U"Spanish", U"es" }, - { U"Sundanese", U"su" }, - { U"Swahili", U"sw" }, - { U"Swati", U"ss" }, - { U"Swedish", U"sv" }, - { U"Tamil", U"ta" }, - { U"Telugu", U"te" }, - { U"Tajik", U"tg" }, - { U"Thai", U"th" }, - { U"Tigrinya", U"ti" }, - { U"Tibetan", U"bo" }, - { U"Turkmen", U"tk" }, - { U"Tagalog", U"tl" }, - { U"Tswana", U"tn" }, - { U"Tonga", U"to" }, - { U"Turkish", U"tr" }, - { U"Tsonga", U"ts" }, - { U"Tatar", U"tt" }, - { U"Twi", U"tw" }, - { U"Tahitian", U"ty" }, - { U"Uighur", U"ug" }, - { U"Ukrainian", U"uk" }, - { U"Urdu", U"ur" }, - { U"Uzbek", U"uz" }, - { U"Venda", U"ve" }, - { U"Vietnamese", U"vi" }, - { U"Volapük", U"vo" }, - { U"Walloon", U"wa" }, - { U"Welsh", U"cy" }, - { U"Wolof", U"wo" }, - { U"Western Frisian", U"fy" }, - { U"Xhosa", U"xh" }, - { U"Yiddish", U"yi" }, - { U"Yoruba", U"yo" }, - { U"Zhuang", U"za" }, - { U"Zulu", U"zu" }, - { String(), String() } -}; - -static CodeInfo scripts[] = { - { U"Custom", U"Qaaa" }, - { U"-", U"-" }, - { U"Adlam", U"Adlm" }, - { U"Afaka", U"Afak" }, - { U"Caucasian Albanian", U"Aghb" }, - { U"Ahom", U"Ahom" }, - { U"Arabic", U"Arab" }, - { U"Imperial Aramaic", U"Armi" }, - { U"Armenian", U"Armn" }, - { U"Avestan", U"Avst" }, - { U"Balinese", U"Bali" }, - { U"Bamum", U"Bamu" }, - { U"Bassa Vah", U"Bass" }, - { U"Batak", U"Batk" }, - { U"Bengali", U"Beng" }, - { U"Bhaiksuki", U"Bhks" }, - { U"Blissymbols", U"Blis" }, - { U"Bopomofo", U"Bopo" }, - { U"Brahmi", U"Brah" }, - { U"Braille", U"Brai" }, - { U"Buginese", U"Bugi" }, - { U"Buhid", U"Buhd" }, - { U"Chakma", U"Cakm" }, - { U"Unified Canadian Aboriginal", U"Cans" }, - { U"Carian", U"Cari" }, - { U"Cham", U"Cham" }, - { U"Cherokee", U"Cher" }, - { U"Chorasmian", U"Chrs" }, - { U"Cirth", U"Cirt" }, - { U"Coptic", U"Copt" }, - { U"Cypro-Minoan", U"Cpmn" }, - { U"Cypriot", U"Cprt" }, - { U"Cyrillic", U"Cyrl" }, - { U"Devanagari", U"Deva" }, - { U"Dives Akuru", U"Diak" }, - { U"Dogra", U"Dogr" }, - { U"Deseret", U"Dsrt" }, - { U"Duployan", U"Dupl" }, - { U"Egyptian demotic", U"Egyd" }, - { U"Egyptian hieratic", U"Egyh" }, - { U"Egyptian hieroglyphs", U"Egyp" }, - { U"Elbasan", U"Elba" }, - { U"Elymaic", U"Elym" }, - { U"Ethiopic", U"Ethi" }, - { U"Khutsuri", U"Geok" }, - { U"Georgian", U"Geor" }, - { U"Glagolitic", U"Glag" }, - { U"Gunjala Gondi", U"Gong" }, - { U"Masaram Gondi", U"Gonm" }, - { U"Gothic", U"Goth" }, - { U"Grantha", U"Gran" }, - { U"Greek", U"Grek" }, - { U"Gujarati", U"Gujr" }, - { U"Gurmukhi", U"Guru" }, - { U"Hangul", U"Hang" }, - { U"Han", U"Hani" }, - { U"Hanunoo", U"Hano" }, - { U"Hatran", U"Hatr" }, - { U"Hebrew", U"Hebr" }, - { U"Hiragana", U"Hira" }, - { U"Anatolian Hieroglyphs", U"Hluw" }, - { U"Pahawh Hmong", U"Hmng" }, - { U"Nyiakeng Puachue Hmong", U"Hmnp" }, - { U"Old Hungarian", U"Hung" }, - { U"Indus", U"Inds" }, - { U"Old Italic", U"Ital" }, - { U"Javanese", U"Java" }, - { U"Jurchen", U"Jurc" }, - { U"Kayah Li", U"Kali" }, - { U"Katakana", U"Kana" }, - { U"Kharoshthi", U"Khar" }, - { U"Khmer", U"Khmr" }, - { U"Khojki", U"Khoj" }, - { U"Khitan large script", U"Kitl" }, - { U"Khitan small script", U"Kits" }, - { U"Kannada", U"Knda" }, - { U"Kpelle", U"Kpel" }, - { U"Kaithi", U"Kthi" }, - { U"Tai Tham", U"Lana" }, - { U"Lao", U"Laoo" }, - { U"Latin", U"Latn" }, - { U"Leke", U"Leke" }, - { U"Lepcha", U"Lepc" }, - { U"Limbu", U"Limb" }, - { U"Linear A", U"Lina" }, - { U"Linear B", U"Linb" }, - { U"Lisu", U"Lisu" }, - { U"Loma", U"Loma" }, - { U"Lycian", U"Lyci" }, - { U"Lydian", U"Lydi" }, - { U"Mahajani", U"Mahj" }, - { U"Makasar", U"Maka" }, - { U"Mandaic", U"Mand" }, - { U"Manichaean", U"Mani" }, - { U"Marchen", U"Marc" }, - { U"Mayan Hieroglyphs", U"Maya" }, - { U"Medefaidrin", U"Medf" }, - { U"Mende Kikakui", U"Mend" }, - { U"Meroitic Cursive", U"Merc" }, - { U"Meroitic Hieroglyphs", U"Mero" }, - { U"Malayalam", U"Mlym" }, - { U"Modi", U"Modi" }, - { U"Mongolian", U"Mong" }, - { U"Moon", U"Moon" }, - { U"Mro", U"Mroo" }, - { U"Meitei Mayek", U"Mtei" }, - { U"Multani", U"Mult" }, - { U"Myanmar (Burmese)", U"Mymr" }, - { U"Nandinagari", U"Nand" }, - { U"Old North Arabian", U"Narb" }, - { U"Nabataean", U"Nbat" }, - { U"Newa", U"Newa" }, - { U"Naxi Dongba", U"Nkdb" }, - { U"Nakhi Geba", U"Nkgb" }, - { U"N’Ko", U"Nkoo" }, - { U"Nüshu", U"Nshu" }, - { U"Ogham", U"Ogam" }, - { U"Ol Chiki", U"Olck" }, - { U"Old Turkic", U"Orkh" }, - { U"Oriya", U"Orya" }, - { U"Osage", U"Osge" }, - { U"Osmanya", U"Osma" }, - { U"Old Uyghur", U"Ougr" }, - { U"Palmyrene", U"Palm" }, - { U"Pau Cin Hau", U"Pauc" }, - { U"Proto-Cuneiform", U"Pcun" }, - { U"Proto-Elamite", U"Pelm" }, - { U"Old Permic", U"Perm" }, - { U"Phags-pa", U"Phag" }, - { U"Inscriptional Pahlavi", U"Phli" }, - { U"Psalter Pahlavi", U"Phlp" }, - { U"Book Pahlavi", U"Phlv" }, - { U"Phoenician", U"Phnx" }, - { U"Klingon", U"Piqd" }, - { U"Miao", U"Plrd" }, - { U"Inscriptional Parthian", U"Prti" }, - { U"Proto-Sinaitic", U"Psin" }, - { U"Ranjana", U"Ranj" }, - { U"Rejang", U"Rjng" }, - { U"Hanifi Rohingya", U"Rohg" }, - { U"Rongorongo", U"Roro" }, - { U"Runic", U"Runr" }, - { U"Samaritan", U"Samr" }, - { U"Sarati", U"Sara" }, - { U"Old South Arabian", U"Sarb" }, - { U"Saurashtra", U"Saur" }, - { U"SignWriting", U"Sgnw" }, - { U"Shavian", U"Shaw" }, - { U"Sharada", U"Shrd" }, - { U"Shuishu", U"Shui" }, - { U"Siddham", U"Sidd" }, - { U"Khudawadi", U"Sind" }, - { U"Sinhala", U"Sinh" }, - { U"Sogdian", U"Sogd" }, - { U"Old Sogdian", U"Sogo" }, - { U"Sora Sompeng", U"Sora" }, - { U"Soyombo", U"Soyo" }, - { U"Sundanese", U"Sund" }, - { U"Syloti Nagri", U"Sylo" }, - { U"Syriac", U"Syrc" }, - { U"Tagbanwa", U"Tagb" }, - { U"Takri", U"Takr" }, - { U"Tai Le", U"Tale" }, - { U"New Tai Lue", U"Talu" }, - { U"Tamil", U"Taml" }, - { U"Tangut", U"Tang" }, - { U"Tai Viet", U"Tavt" }, - { U"Telugu", U"Telu" }, - { U"Tengwar", U"Teng" }, - { U"Tifinagh", U"Tfng" }, - { U"Tagalog", U"Tglg" }, - { U"Thaana", U"Thaa" }, - { U"Thai", U"Thai" }, - { U"Tibetan", U"Tibt" }, - { U"Tirhuta", U"Tirh" }, - { U"Tangsa", U"Tnsa" }, - { U"Toto", U"Toto" }, - { U"Ugaritic", U"Ugar" }, - { U"Vai", U"Vaii" }, - { U"Visible Speech", U"Visp" }, - { U"Vithkuqi", U"Vith" }, - { U"Warang Citi", U"Wara" }, - { U"Wancho", U"Wcho" }, - { U"Woleai", U"Wole" }, - { U"Old Persian", U"Xpeo" }, - { U"Cuneiform", U"Xsux" }, - { U"Yezidi", U"Yezi" }, - { U"Yi", U"Yiii" }, - { U"Zanabazar Square", U"Zanb" }, - { String(), String() } -}; - -/*************************************************************************/ /* Page 1 callbacks: Rendering Options */ /*************************************************************************/ @@ -1159,19 +767,17 @@ void DynamicFontImportSettings::_range_update(int32_t p_start, int32_t p_end) { /*************************************************************************/ void DynamicFontImportSettings::_lang_add() { - menu_langs->set_position(lang_list->get_screen_position() + lang_list->get_local_mouse_position()); - menu_langs->reset_size(); - menu_langs->popup(); + locale_select->popup_locale_dialog(); } -void DynamicFontImportSettings::_lang_add_item(int p_option) { +void DynamicFontImportSettings::_lang_add_item(const String &p_locale) { TreeItem *lang_item = lang_list->create_item(lang_list_root); ERR_FAIL_NULL(lang_item); lang_item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); lang_item->set_editable(0, true); lang_item->set_checked(0, false); - lang_item->set_text(1, langs[p_option].code); + lang_item->set_text(1, p_locale); lang_item->set_editable(1, true); lang_item->add_button(2, lang_list->get_theme_icon("Remove", "EditorIcons"), BUTTON_REMOVE_VAR, false, TTR("Remove")); lang_item->set_button_color(2, 0, Color(1, 1, 1, 0.75)); @@ -1230,7 +836,7 @@ void DynamicFontImportSettings::_script_add_item(int p_option) { script_item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); script_item->set_editable(0, true); script_item->set_checked(0, false); - script_item->set_text(1, scripts[p_option].code); + script_item->set_text(1, script_codes[p_option]); script_item->set_editable(1, true); script_item->add_button(2, lang_list->get_theme_icon("Remove", "EditorIcons"), BUTTON_REMOVE_VAR, false, TTR("Remove")); script_item->set_button_color(2, 0, Color(1, 1, 1, 0.75)); @@ -1688,26 +1294,15 @@ DynamicFontImportSettings::DynamicFontImportSettings() { // Popup menus - menu_langs = memnew(PopupMenu); - menu_langs->set_name("Language"); - for (int i = 0; !langs[i].name.is_empty(); i++) { - if (langs[i].name == "-") { - menu_langs->add_separator(); - } else { - menu_langs->add_item(langs[i].name + " (" + langs[i].code + ")", i); - } - } - add_child(menu_langs); - menu_langs->connect("id_pressed", callable_mp(this, &DynamicFontImportSettings::_lang_add_item)); + locale_select = memnew(EditorLocaleDialog); + locale_select->connect("locale_selected", callable_mp(this, &DynamicFontImportSettings::_lang_add_item)); + add_child(locale_select); menu_scripts = memnew(PopupMenu); menu_scripts->set_name("Script"); - for (int i = 0; !scripts[i].name.is_empty(); i++) { - if (scripts[i].name == "-") { - menu_scripts->add_separator(); - } else { - menu_scripts->add_item(scripts[i].name + " (" + scripts[i].code + ")", i); - } + script_codes = TranslationServer::get_singleton()->get_all_scripts(); + for (int i = 0; i < script_codes.size(); i++) { + menu_scripts->add_item(TranslationServer::get_singleton()->get_script_name(script_codes[i]) + " (" + script_codes[i] + ")", i); } add_child(menu_scripts); menu_scripts->connect("id_pressed", callable_mp(this, &DynamicFontImportSettings::_script_add_item)); diff --git a/editor/import/dynamicfont_import_settings.h b/editor/import/dynamicfont_import_settings.h index 89665ae476..5d37f58b9b 100644 --- a/editor/import/dynamicfont_import_settings.h +++ b/editor/import/dynamicfont_import_settings.h @@ -33,6 +33,7 @@ #include "editor/editor_file_dialog.h" #include "editor/editor_inspector.h" +#include "editor/editor_locale_dialog.h" #include "editor/import/resource_importer_dynamicfont.h" @@ -67,6 +68,9 @@ class DynamicFontImportSettings : public ConfirmationDialog { List<ResourceImporter::ImportOption> options_variations; List<ResourceImporter::ImportOption> options_general; + EditorLocaleDialog *locale_select; + Vector<String> script_codes; + // Root layout Label *label_warn = nullptr; TabContainer *main_pages = nullptr; @@ -122,7 +126,6 @@ class DynamicFontImportSettings : public ConfirmationDialog { Button *add_script = nullptr; Button *add_ot = nullptr; - PopupMenu *menu_langs = nullptr; PopupMenu *menu_scripts = nullptr; PopupMenu *menu_ot = nullptr; PopupMenu *menu_ot_ss = nullptr; @@ -142,7 +145,7 @@ class DynamicFontImportSettings : public ConfirmationDialog { Label *label_ot = nullptr; void _lang_add(); - void _lang_add_item(int p_option); + void _lang_add_item(const String &p_locale); void _lang_remove(Object *p_item, int p_column, int p_id); void _script_add(); diff --git a/editor/import/resource_importer_csv_translation.cpp b/editor/import/resource_importer_csv_translation.cpp index 448b318c64..f0ee14bdcb 100644 --- a/editor/import/resource_importer_csv_translation.cpp +++ b/editor/import/resource_importer_csv_translation.cpp @@ -99,8 +99,7 @@ Error ResourceImporterCSVTranslation::import(const String &p_source_file, const Vector<Ref<Translation>> translations; for (int i = 1; i < line.size(); i++) { - String locale = line[i]; - ERR_FAIL_COND_V_MSG(!TranslationServer::is_locale_valid(locale), ERR_PARSE_ERROR, "Error importing CSV translation: '" + locale + "' is not a valid locale."); + String locale = TranslationServer::get_singleton()->standardize_locale(line[i]); locales.push_back(locale); Ref<Translation> translation; diff --git a/editor/localization_editor.cpp b/editor/localization_editor.cpp index a902b070f4..1e9e2fc09b 100644 --- a/editor/localization_editor.cpp +++ b/editor/localization_editor.cpp @@ -32,6 +32,7 @@ #include "core/string/translation.h" #include "editor_node.h" +#include "editor_scale.h" #include "editor_translation_parser.h" #include "pot_generator.h" #include "scene/gui/control.h" @@ -175,10 +176,27 @@ void LocalizationEditor::_translation_res_select() { if (updating_translations) { return; } - call_deferred(SNAME("update_translations")); } +void LocalizationEditor::_translation_res_option_popup(bool p_arrow_clicked) { + TreeItem *ed = translation_remap_options->get_edited(); + ERR_FAIL_COND(!ed); + + locale_select->set_locale(ed->get_tooltip(1)); + locale_select->popup_locale_dialog(); +} + +void LocalizationEditor::_translation_res_option_selected(const String &p_locale) { + TreeItem *ed = translation_remap_options->get_edited(); + ERR_FAIL_COND(!ed); + + ed->set_text(1, TranslationServer::get_singleton()->get_locale_name(p_locale)); + ed->set_tooltip(1, p_locale); + + LocalizationEditor::_translation_res_option_changed(); +} + void LocalizationEditor::_translation_res_option_changed() { if (updating_translations) { return; @@ -198,20 +216,11 @@ void LocalizationEditor::_translation_res_option_changed() { String key = k->get_metadata(0); int idx = ed->get_metadata(0); String path = ed->get_metadata(1); - int which = ed->get_range(1); - - Vector<String> langs = TranslationServer::get_all_locales(); - - ERR_FAIL_INDEX(which, langs.size()); + String locale = ed->get_tooltip(1); ERR_FAIL_COND(!remaps.has(key)); PackedStringArray r = remaps[key]; - ERR_FAIL_INDEX(idx, r.size()); - if (translation_locales_idxs_remap.size() > which) { - r.set(idx, path + ":" + langs[translation_locales_idxs_remap[which]]); - } else { - r.set(idx, path + ":" + langs[which]); - } + r.set(idx, path + ":" + locale); remaps[key] = r; updating_translations = true; @@ -289,86 +298,6 @@ void LocalizationEditor::_translation_res_option_delete(Object *p_item, int p_co undo_redo->commit_action(); } -void LocalizationEditor::_translation_filter_option_changed() { - int sel_id = translation_locale_filter_mode->get_selected_id(); - TreeItem *t = translation_filter->get_edited(); - String locale = t->get_tooltip(0); - bool checked = t->is_checked(0); - - Variant prev; - Array f_locales_all; - - if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/locale_filter")) { - f_locales_all = ProjectSettings::get_singleton()->get("internationalization/locale/locale_filter"); - prev = f_locales_all; - - if (f_locales_all.size() != 2) { - f_locales_all.clear(); - f_locales_all.append(sel_id); - f_locales_all.append(Array()); - } - } else { - f_locales_all.append(sel_id); - f_locales_all.append(Array()); - } - - Array f_locales = f_locales_all[1]; - int l_idx = f_locales.find(locale); - - if (checked) { - if (l_idx == -1) { - f_locales.append(locale); - } - } else { - if (l_idx != -1) { - f_locales.remove_at(l_idx); - } - } - - f_locales.sort(); - - undo_redo->create_action(TTR("Changed Locale Filter")); - undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/locale_filter", f_locales_all); - undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/locale_filter", prev); - undo_redo->add_do_method(this, "update_translations"); - undo_redo->add_undo_method(this, "update_translations"); - undo_redo->add_do_method(this, "emit_signal", localization_changed); - undo_redo->add_undo_method(this, "emit_signal", localization_changed); - undo_redo->commit_action(); -} - -void LocalizationEditor::_translation_filter_mode_changed(int p_mode) { - int sel_id = translation_locale_filter_mode->get_selected_id(); - - Variant prev; - Array f_locales_all; - - if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/locale_filter")) { - f_locales_all = ProjectSettings::get_singleton()->get("internationalization/locale/locale_filter"); - prev = f_locales_all; - - if (f_locales_all.size() != 2) { - f_locales_all.clear(); - f_locales_all.append(sel_id); - f_locales_all.append(Array()); - } else { - f_locales_all[0] = sel_id; - } - } else { - f_locales_all.append(sel_id); - f_locales_all.append(Array()); - } - - undo_redo->create_action(TTR("Changed Locale Filter Mode")); - undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/locale_filter", f_locales_all); - undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/locale_filter", prev); - undo_redo->add_do_method(this, "update_translations"); - undo_redo->add_undo_method(this, "update_translations"); - undo_redo->add_do_method(this, "emit_signal", localization_changed); - undo_redo->add_undo_method(this, "emit_signal", localization_changed); - undo_redo->commit_action(); -} - void LocalizationEditor::_pot_add(const PackedStringArray &p_paths) { PackedStringArray pot_translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations_pot_files"); for (int i = 0; i < p_paths.size(); i++) { @@ -452,64 +381,6 @@ void LocalizationEditor::update_translations() { } } - Vector<String> langs = TranslationServer::get_all_locales(); - Vector<String> names = TranslationServer::get_all_locale_names(); - - // Update filter tab - Array l_filter_all; - - bool is_arr_empty = true; - if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/locale_filter")) { - l_filter_all = ProjectSettings::get_singleton()->get("internationalization/locale/locale_filter"); - - if (l_filter_all.size() == 2) { - translation_locale_filter_mode->select(l_filter_all[0]); - is_arr_empty = false; - } - } - if (is_arr_empty) { - l_filter_all.append(0); - l_filter_all.append(Array()); - translation_locale_filter_mode->select(0); - } - - int filter_mode = l_filter_all[0]; - Array l_filter = l_filter_all[1]; - - int s = names.size(); - bool is_short_list_when_show_all_selected = filter_mode == SHOW_ALL_LOCALES && translation_filter_treeitems.size() < s; - bool is_full_list_when_show_only_selected = filter_mode == SHOW_ONLY_SELECTED_LOCALES && translation_filter_treeitems.size() == s; - bool should_recreate_locales_list = is_short_list_when_show_all_selected || is_full_list_when_show_only_selected; - - if (!translation_locales_list_created || should_recreate_locales_list) { - translation_locales_list_created = true; - translation_filter->clear(); - root = translation_filter->create_item(nullptr); - translation_filter->set_hide_root(true); - translation_filter_treeitems.clear(); - for (int i = 0; i < s; i++) { - String n = names[i]; - String l = langs[i]; - bool is_checked = l_filter.has(l); - if (filter_mode == SHOW_ONLY_SELECTED_LOCALES && !is_checked) { - continue; - } - - TreeItem *t = translation_filter->create_item(root); - t->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); - t->set_text(0, vformat("[%s] %s", l, n)); - t->set_editable(0, true); - t->set_tooltip(0, l); - t->set_checked(0, is_checked); - translation_filter_treeitems.push_back(t); - } - } else { - for (int i = 0; i < translation_filter_treeitems.size(); i++) { - TreeItem *t = translation_filter_treeitems[i]; - t->set_checked(0, l_filter.has(t->get_tooltip(0))); - } - } - // Update translation remaps. String remap_selected; if (translation_remap->get_selected()) { @@ -524,32 +395,6 @@ void LocalizationEditor::update_translations() { translation_remap_options->set_hide_root(true); translation_res_option_add_button->set_disabled(true); - translation_locales_idxs_remap.clear(); - translation_locales_idxs_remap.resize(l_filter.size()); - int fl_idx_count = translation_locales_idxs_remap.size(); - - String langnames = ""; - int l_idx = 0; - for (int i = 0; i < names.size(); i++) { - if (filter_mode == SHOW_ONLY_SELECTED_LOCALES && fl_idx_count != 0) { - if (l_filter.size() > 0) { - if (l_filter.find(langs[i]) != -1) { - if (langnames.length() > 0) { - langnames += ","; - } - langnames += vformat("[%s] %s", langs[i], names[i]); - translation_locales_idxs_remap.write[l_idx] = i; - l_idx++; - } - } - } else { - if (i > 0) { - langnames += ","; - } - langnames += vformat("[%s] %s", langs[i], names[i]); - } - } - if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/translation_remaps")) { Dictionary remaps = ProjectSettings::get_singleton()->get("internationalization/locale/translation_remaps"); List<Variant> rk; @@ -584,21 +429,11 @@ void LocalizationEditor::update_translations() { t2->set_tooltip(0, path); t2->set_metadata(0, j); t2->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), 0, false, TTR("Remove")); - t2->set_cell_mode(1, TreeItem::CELL_MODE_RANGE); - t2->set_text(1, langnames); + t2->set_cell_mode(1, TreeItem::CELL_MODE_CUSTOM); + t2->set_text(1, TranslationServer::get_singleton()->get_locale_name(locale)); t2->set_editable(1, true); t2->set_metadata(1, path); - int idx = langs.find(locale); - if (idx < 0) { - idx = 0; - } - - int f_idx = translation_locales_idxs_remap.find(idx); - if (f_idx != -1 && fl_idx_count > 0 && filter_mode == SHOW_ONLY_SELECTED_LOCALES) { - t2->set_range(1, f_idx); - } else { - t2->set_range(1, idx); - } + t2->set_tooltip(1, locale); } } } @@ -637,9 +472,6 @@ LocalizationEditor::LocalizationEditor() { updating_translations = false; localization_changed = "localization_changed"; - translation_locales_idxs_remap = Vector<int>(); - translation_locales_list_created = false; - TabContainer *translations = memnew(TabContainer); translations->set_tab_alignment(TabContainer::ALIGNMENT_LEFT); translations->set_v_size_flags(Control::SIZE_EXPAND_FILL); @@ -669,6 +501,10 @@ LocalizationEditor::LocalizationEditor() { translation_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); tmc->add_child(translation_list); + locale_select = memnew(EditorLocaleDialog); + locale_select->connect("locale_selected", callable_mp(this, &LocalizationEditor::_translation_res_option_selected)); + add_child(locale_select); + translation_file_open = memnew(EditorFileDialog); translation_file_open->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILES); translation_file_open->connect("files_selected", callable_mp(this, &LocalizationEditor::_translation_add)); @@ -731,10 +567,11 @@ LocalizationEditor::LocalizationEditor() { translation_remap_options->set_column_expand(0, true); translation_remap_options->set_column_clip_content(0, true); translation_remap_options->set_column_expand(1, false); - translation_remap_options->set_column_clip_content(1, true); - translation_remap_options->set_column_custom_minimum_width(1, 200); + translation_remap_options->set_column_clip_content(1, false); + translation_remap_options->set_column_custom_minimum_width(1, 250); translation_remap_options->connect("item_edited", callable_mp(this, &LocalizationEditor::_translation_res_option_changed)); translation_remap_options->connect("button_pressed", callable_mp(this, &LocalizationEditor::_translation_res_option_delete)); + translation_remap_options->connect("custom_popup_edited", callable_mp(this, &LocalizationEditor::_translation_res_option_popup)); tmc->add_child(translation_remap_options); translation_res_option_file_open_dialog = memnew(EditorFileDialog); @@ -745,32 +582,6 @@ LocalizationEditor::LocalizationEditor() { { VBoxContainer *tvb = memnew(VBoxContainer); - tvb->set_name(TTR("Locales Filter")); - translations->add_child(tvb); - - VBoxContainer *tmc = memnew(VBoxContainer); - tmc->set_v_size_flags(Control::SIZE_EXPAND_FILL); - tvb->add_child(tmc); - - translation_locale_filter_mode = memnew(OptionButton); - translation_locale_filter_mode->add_item(TTR("Show All Locales"), SHOW_ALL_LOCALES); - translation_locale_filter_mode->add_item(TTR("Show Selected Locales Only"), SHOW_ONLY_SELECTED_LOCALES); - translation_locale_filter_mode->select(0); - translation_locale_filter_mode->connect("item_selected", callable_mp(this, &LocalizationEditor::_translation_filter_mode_changed)); - tmc->add_margin_child(TTR("Filter mode:"), translation_locale_filter_mode); - - Label *l = memnew(Label(TTR("Locales:"))); - l->set_theme_type_variation("HeaderSmall"); - tmc->add_child(l); - translation_filter = memnew(Tree); - translation_filter->set_v_size_flags(Control::SIZE_EXPAND_FILL); - translation_filter->set_columns(1); - translation_filter->connect("item_edited", callable_mp(this, &LocalizationEditor::_translation_filter_option_changed)); - tmc->add_child(translation_filter); - } - - { - VBoxContainer *tvb = memnew(VBoxContainer); tvb->set_name(TTR("POT Generation")); translations->add_child(tvb); diff --git a/editor/localization_editor.h b/editor/localization_editor.h index 4c77aca397..cad07dd336 100644 --- a/editor/localization_editor.h +++ b/editor/localization_editor.h @@ -33,18 +33,15 @@ #include "core/object/undo_redo.h" #include "editor_file_dialog.h" +#include "editor_locale_dialog.h" #include "scene/gui/tree.h" class LocalizationEditor : public VBoxContainer { GDCLASS(LocalizationEditor, VBoxContainer); - enum LocaleFilter { - SHOW_ALL_LOCALES, - SHOW_ONLY_SELECTED_LOCALES, - }; - Tree *translation_list; + EditorLocaleDialog *locale_select; EditorFileDialog *translation_file_open; Button *translation_res_option_add_button; @@ -52,11 +49,6 @@ class LocalizationEditor : public VBoxContainer { EditorFileDialog *translation_res_option_file_open_dialog; Tree *translation_remap; Tree *translation_remap_options; - Tree *translation_filter; - bool translation_locales_list_created; - OptionButton *translation_locale_filter_mode; - Vector<TreeItem *> translation_filter_treeitems; - Vector<int> translation_locales_idxs_remap; Tree *translation_pot_list; EditorFileDialog *pot_file_open_dialog; @@ -78,9 +70,8 @@ class LocalizationEditor : public VBoxContainer { void _translation_res_option_add(const PackedStringArray &p_paths); void _translation_res_option_changed(); void _translation_res_option_delete(Object *p_item, int p_column, int p_button); - - void _translation_filter_option_changed(); - void _translation_filter_mode_changed(int p_mode); + void _translation_res_option_popup(bool p_arrow_clicked); + void _translation_res_option_selected(const String &p_locale); void _pot_add(const PackedStringArray &p_paths); void _pot_delete(Object *p_item, int p_column, int p_button); diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index 481ff1a781..c971bb6473 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -506,12 +506,16 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: } break; case Variant::STRING: { - if (hint == PROPERTY_HINT_FILE || hint == PROPERTY_HINT_GLOBAL_FILE) { + if (hint == PROPERTY_HINT_LOCALE_ID) { + List<String> names; + names.push_back(TTR("Locale...")); + names.push_back(TTR("Clear")); + config_action_buttons(names); + } else if (hint == PROPERTY_HINT_FILE || hint == PROPERTY_HINT_GLOBAL_FILE) { List<String> names; names.push_back(TTR("File...")); names.push_back(TTR("Clear")); config_action_buttons(names); - } else if (hint == PROPERTY_HINT_DIR || hint == PROPERTY_HINT_GLOBAL_DIR) { List<String> names; names.push_back(TTR("Dir...")); @@ -1034,6 +1038,14 @@ void CustomPropertyEditor::_file_selected(String p_file) { } } +void CustomPropertyEditor::_locale_selected(String p_locale) { + if (type == Variant::STRING && hint == PROPERTY_HINT_LOCALE_ID) { + v = p_locale; + emit_signal(SNAME("variant_changed")); + hide(); + } +} + void CustomPropertyEditor::_type_create_selected(int p_idx) { if (type == Variant::INT || type == Variant::FLOAT) { float newval = 0; @@ -1177,7 +1189,8 @@ void CustomPropertyEditor::_action_pressed(int p_which) { case Variant::STRING: { if (hint == PROPERTY_HINT_MULTILINE_TEXT) { hide(); - + } else if (hint == PROPERTY_HINT_LOCALE_ID) { + locale->popup_locale_dialog(); } else if (hint == PROPERTY_HINT_FILE || hint == PROPERTY_HINT_GLOBAL_FILE) { if (p_which == 0) { if (hint == PROPERTY_HINT_FILE) { @@ -1821,6 +1834,12 @@ CustomPropertyEditor::CustomPropertyEditor() { file->connect("file_selected", callable_mp(this, &CustomPropertyEditor::_file_selected)); file->connect("dir_selected", callable_mp(this, &CustomPropertyEditor::_file_selected)); + locale = memnew(EditorLocaleDialog); + value_vbox->add_child(locale); + locale->hide(); + + locale->connect("locale_selected", callable_mp(this, &CustomPropertyEditor::_locale_selected)); + error = memnew(ConfirmationDialog); error->set_title(TTR("Error!")); value_vbox->add_child(error); diff --git a/editor/property_editor.h b/editor/property_editor.h index 9d88aaf26d..298acb3c01 100644 --- a/editor/property_editor.h +++ b/editor/property_editor.h @@ -32,6 +32,7 @@ #define PROPERTY_EDITOR_H #include "editor/editor_file_dialog.h" +#include "editor/editor_locale_dialog.h" #include "editor/scene_tree_editor.h" #include "scene/gui/button.h" #include "scene/gui/check_box.h" @@ -97,6 +98,7 @@ class CustomPropertyEditor : public PopupPanel { PopupMenu *menu; SceneTreeDialog *scene_tree; EditorFileDialog *file; + EditorLocaleDialog *locale; ConfirmationDialog *error; String name; Variant::Type type; @@ -136,6 +138,7 @@ class CustomPropertyEditor : public PopupPanel { void _text_edit_changed(); void _file_selected(String p_file); + void _locale_selected(String p_locale); void _modified(String p_string); real_t _parse_real_expression(String text); |