editor_locale_dialog.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. /**************************************************************************/
  2. /* editor_locale_dialog.cpp */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #include "editor_locale_dialog.h"
  31. #include "core/config/project_settings.h"
  32. #include "editor/editor_undo_redo_manager.h"
  33. #include "editor/themes/editor_scale.h"
  34. #include "scene/gui/check_button.h"
  35. #include "scene/gui/line_edit.h"
  36. #include "scene/gui/option_button.h"
  37. #include "scene/gui/tree.h"
  38. void EditorLocaleDialog::_bind_methods() {
  39. ADD_SIGNAL(MethodInfo("locale_selected", PropertyInfo(Variant::STRING, "locale")));
  40. }
  41. void EditorLocaleDialog::ok_pressed() {
  42. if (edit_filters->is_pressed()) {
  43. return; // Do not update, if in filter edit mode.
  44. }
  45. String locale;
  46. if (lang_code->get_text().is_empty()) {
  47. return; // Language code is required.
  48. }
  49. locale = lang_code->get_text();
  50. if (!script_code->get_text().is_empty()) {
  51. locale += "_" + script_code->get_text();
  52. }
  53. if (!country_code->get_text().is_empty()) {
  54. locale += "_" + country_code->get_text();
  55. }
  56. if (!variant_code->get_text().is_empty()) {
  57. locale += "_" + variant_code->get_text();
  58. }
  59. emit_signal(SNAME("locale_selected"), TranslationServer::get_singleton()->standardize_locale(locale));
  60. hide();
  61. }
  62. void EditorLocaleDialog::_item_selected() {
  63. if (updating_lists) {
  64. return;
  65. }
  66. if (edit_filters->is_pressed()) {
  67. return; // Do not update, if in filter edit mode.
  68. }
  69. TreeItem *l = lang_list->get_selected();
  70. if (l) {
  71. lang_code->set_text(l->get_metadata(0).operator String());
  72. }
  73. TreeItem *s = script_list->get_selected();
  74. if (s) {
  75. script_code->set_text(s->get_metadata(0).operator String());
  76. }
  77. TreeItem *c = cnt_list->get_selected();
  78. if (c) {
  79. country_code->set_text(c->get_metadata(0).operator String());
  80. }
  81. }
  82. void EditorLocaleDialog::_toggle_advanced(bool p_checked) {
  83. if (!p_checked) {
  84. script_code->set_text("");
  85. variant_code->set_text("");
  86. }
  87. _update_tree();
  88. }
  89. void EditorLocaleDialog::_post_popup() {
  90. ConfirmationDialog::_post_popup();
  91. if (!locale_set) {
  92. lang_code->set_text("");
  93. script_code->set_text("");
  94. country_code->set_text("");
  95. variant_code->set_text("");
  96. }
  97. edit_filters->set_pressed(false);
  98. _update_tree();
  99. }
  100. void EditorLocaleDialog::_filter_lang_option_changed() {
  101. TreeItem *t = lang_list->get_edited();
  102. String lang = t->get_metadata(0);
  103. bool checked = t->is_checked(0);
  104. Variant prev;
  105. Array f_lang_all;
  106. if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/language_filter")) {
  107. f_lang_all = GLOBAL_GET("internationalization/locale/language_filter");
  108. prev = f_lang_all;
  109. }
  110. int l_idx = f_lang_all.find(lang);
  111. if (checked) {
  112. if (l_idx == -1) {
  113. f_lang_all.append(lang);
  114. }
  115. } else {
  116. if (l_idx != -1) {
  117. f_lang_all.remove_at(l_idx);
  118. }
  119. }
  120. f_lang_all.sort();
  121. EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
  122. undo_redo->create_action(TTR("Changed Locale Language Filter"));
  123. undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/language_filter", f_lang_all);
  124. undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/language_filter", prev);
  125. undo_redo->commit_action();
  126. }
  127. void EditorLocaleDialog::_filter_script_option_changed() {
  128. TreeItem *t = script_list->get_edited();
  129. String scr_code = t->get_metadata(0);
  130. bool checked = t->is_checked(0);
  131. Variant prev;
  132. Array f_script_all;
  133. if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/script_filter")) {
  134. f_script_all = GLOBAL_GET("internationalization/locale/script_filter");
  135. prev = f_script_all;
  136. }
  137. int l_idx = f_script_all.find(scr_code);
  138. if (checked) {
  139. if (l_idx == -1) {
  140. f_script_all.append(scr_code);
  141. }
  142. } else {
  143. if (l_idx != -1) {
  144. f_script_all.remove_at(l_idx);
  145. }
  146. }
  147. f_script_all.sort();
  148. EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
  149. undo_redo->create_action(TTR("Changed Locale Script Filter"));
  150. undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/script_filter", f_script_all);
  151. undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/script_filter", prev);
  152. undo_redo->commit_action();
  153. }
  154. void EditorLocaleDialog::_filter_cnt_option_changed() {
  155. TreeItem *t = cnt_list->get_edited();
  156. String cnt = t->get_metadata(0);
  157. bool checked = t->is_checked(0);
  158. Variant prev;
  159. Array f_cnt_all;
  160. if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/country_filter")) {
  161. f_cnt_all = GLOBAL_GET("internationalization/locale/country_filter");
  162. prev = f_cnt_all;
  163. }
  164. int l_idx = f_cnt_all.find(cnt);
  165. if (checked) {
  166. if (l_idx == -1) {
  167. f_cnt_all.append(cnt);
  168. }
  169. } else {
  170. if (l_idx != -1) {
  171. f_cnt_all.remove_at(l_idx);
  172. }
  173. }
  174. f_cnt_all.sort();
  175. EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
  176. undo_redo->create_action(TTR("Changed Locale Country Filter"));
  177. undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/country_filter", f_cnt_all);
  178. undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/country_filter", prev);
  179. undo_redo->commit_action();
  180. }
  181. void EditorLocaleDialog::_filter_mode_changed(int p_mode) {
  182. int f_mode = filter_mode->get_selected_id();
  183. Variant prev;
  184. if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/locale_filter_mode")) {
  185. prev = GLOBAL_GET("internationalization/locale/locale_filter_mode");
  186. }
  187. EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
  188. undo_redo->create_action(TTR("Changed Locale Filter Mode"));
  189. undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/locale_filter_mode", f_mode);
  190. undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/locale_filter_mode", prev);
  191. undo_redo->commit_action();
  192. _update_tree();
  193. }
  194. void EditorLocaleDialog::_edit_filters(bool p_checked) {
  195. _update_tree();
  196. }
  197. void EditorLocaleDialog::_update_tree() {
  198. updating_lists = true;
  199. int filter = SHOW_ALL_LOCALES;
  200. if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/locale_filter_mode")) {
  201. filter = GLOBAL_GET("internationalization/locale/locale_filter_mode");
  202. }
  203. Array f_lang_all;
  204. if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/language_filter")) {
  205. f_lang_all = GLOBAL_GET("internationalization/locale/language_filter");
  206. }
  207. Array f_cnt_all;
  208. if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/country_filter")) {
  209. f_cnt_all = GLOBAL_GET("internationalization/locale/country_filter");
  210. }
  211. Array f_script_all;
  212. if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/script_filter")) {
  213. f_script_all = GLOBAL_GET("internationalization/locale/script_filter");
  214. }
  215. bool is_edit_mode = edit_filters->is_pressed();
  216. filter_mode->select(filter);
  217. // Hide text advanced edit and disable OK button if in filter edit mode.
  218. advanced->set_visible(!is_edit_mode);
  219. hb_locale->set_visible(!is_edit_mode && advanced->is_pressed());
  220. vb_script_list->set_visible(advanced->is_pressed());
  221. get_ok_button()->set_disabled(is_edit_mode);
  222. // Update language list.
  223. lang_list->clear();
  224. TreeItem *l_root = lang_list->create_item(nullptr);
  225. lang_list->set_hide_root(true);
  226. Vector<String> languages = TranslationServer::get_singleton()->get_all_languages();
  227. for (const String &E : languages) {
  228. if (is_edit_mode || (filter == SHOW_ALL_LOCALES) || f_lang_all.has(E) || f_lang_all.is_empty()) {
  229. const String &lang = TranslationServer::get_singleton()->get_language_name(E);
  230. TreeItem *t = lang_list->create_item(l_root);
  231. if (is_edit_mode) {
  232. t->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
  233. t->set_editable(0, true);
  234. t->set_checked(0, f_lang_all.has(E));
  235. } else if (lang_code->get_text() == E) {
  236. t->select(0);
  237. }
  238. t->set_text(0, vformat("%s [%s]", lang, E));
  239. t->set_metadata(0, E);
  240. }
  241. }
  242. // Update script list.
  243. script_list->clear();
  244. TreeItem *s_root = script_list->create_item(nullptr);
  245. script_list->set_hide_root(true);
  246. if (!is_edit_mode) {
  247. TreeItem *t = script_list->create_item(s_root);
  248. t->set_text(0, TTR("[Default]"));
  249. t->set_metadata(0, "");
  250. }
  251. Vector<String> scripts = TranslationServer::get_singleton()->get_all_scripts();
  252. for (const String &E : scripts) {
  253. if (is_edit_mode || (filter == SHOW_ALL_LOCALES) || f_script_all.has(E) || f_script_all.is_empty()) {
  254. const String &scr_code = TranslationServer::get_singleton()->get_script_name(E);
  255. TreeItem *t = script_list->create_item(s_root);
  256. if (is_edit_mode) {
  257. t->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
  258. t->set_editable(0, true);
  259. t->set_checked(0, f_script_all.has(E));
  260. } else if (script_code->get_text() == E) {
  261. t->select(0);
  262. }
  263. t->set_text(0, vformat("%s [%s]", scr_code, E));
  264. t->set_metadata(0, E);
  265. }
  266. }
  267. // Update country list.
  268. cnt_list->clear();
  269. TreeItem *c_root = cnt_list->create_item(nullptr);
  270. cnt_list->set_hide_root(true);
  271. if (!is_edit_mode) {
  272. TreeItem *t = cnt_list->create_item(c_root);
  273. t->set_text(0, TTR("[Default]"));
  274. t->set_metadata(0, "");
  275. }
  276. Vector<String> countries = TranslationServer::get_singleton()->get_all_countries();
  277. for (const String &E : countries) {
  278. if (is_edit_mode || (filter == SHOW_ALL_LOCALES) || f_cnt_all.has(E) || f_cnt_all.is_empty()) {
  279. const String &cnt = TranslationServer::get_singleton()->get_country_name(E);
  280. TreeItem *t = cnt_list->create_item(c_root);
  281. if (is_edit_mode) {
  282. t->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
  283. t->set_editable(0, true);
  284. t->set_checked(0, f_cnt_all.has(E));
  285. } else if (country_code->get_text() == E) {
  286. t->select(0);
  287. }
  288. t->set_text(0, vformat("%s [%s]", cnt, E));
  289. t->set_metadata(0, E);
  290. }
  291. }
  292. updating_lists = false;
  293. }
  294. void EditorLocaleDialog::set_locale(const String &p_locale) {
  295. const String &locale = TranslationServer::get_singleton()->standardize_locale(p_locale);
  296. if (locale.is_empty()) {
  297. locale_set = false;
  298. lang_code->set_text("");
  299. script_code->set_text("");
  300. country_code->set_text("");
  301. variant_code->set_text("");
  302. } else {
  303. locale_set = true;
  304. Vector<String> locale_elements = p_locale.split("_");
  305. lang_code->set_text(locale_elements[0]);
  306. if (locale_elements.size() >= 2) {
  307. if (locale_elements[1].length() == 4 && is_ascii_upper_case(locale_elements[1][0]) && is_ascii_lower_case(locale_elements[1][1]) && is_ascii_lower_case(locale_elements[1][2]) && is_ascii_lower_case(locale_elements[1][3])) {
  308. script_code->set_text(locale_elements[1]);
  309. advanced->set_pressed(true);
  310. }
  311. if (locale_elements[1].length() == 2 && is_ascii_upper_case(locale_elements[1][0]) && is_ascii_upper_case(locale_elements[1][1])) {
  312. country_code->set_text(locale_elements[1]);
  313. }
  314. }
  315. if (locale_elements.size() >= 3) {
  316. if (locale_elements[2].length() == 2 && is_ascii_upper_case(locale_elements[2][0]) && is_ascii_upper_case(locale_elements[2][1])) {
  317. country_code->set_text(locale_elements[2]);
  318. } else {
  319. variant_code->set_text(locale_elements[2].to_lower());
  320. advanced->set_pressed(true);
  321. }
  322. }
  323. if (locale_elements.size() >= 4) {
  324. variant_code->set_text(locale_elements[3].to_lower());
  325. advanced->set_pressed(true);
  326. }
  327. }
  328. }
  329. void EditorLocaleDialog::popup_locale_dialog() {
  330. popup_centered_clamped(Size2(1050, 700) * EDSCALE, 0.8);
  331. }
  332. EditorLocaleDialog::EditorLocaleDialog() {
  333. set_title(TTR("Select a Locale"));
  334. VBoxContainer *vb = memnew(VBoxContainer);
  335. {
  336. HBoxContainer *hb_filter = memnew(HBoxContainer);
  337. {
  338. filter_mode = memnew(OptionButton);
  339. filter_mode->add_item(TTR("Show All Locales"), SHOW_ALL_LOCALES);
  340. filter_mode->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  341. filter_mode->add_item(TTR("Show Selected Locales Only"), SHOW_ONLY_SELECTED_LOCALES);
  342. filter_mode->select(0);
  343. filter_mode->connect("item_selected", callable_mp(this, &EditorLocaleDialog::_filter_mode_changed));
  344. hb_filter->add_child(filter_mode);
  345. }
  346. {
  347. edit_filters = memnew(CheckButton);
  348. edit_filters->set_text(TTR("Edit Filters"));
  349. edit_filters->set_toggle_mode(true);
  350. edit_filters->set_pressed(false);
  351. edit_filters->connect("toggled", callable_mp(this, &EditorLocaleDialog::_edit_filters));
  352. hb_filter->add_child(edit_filters);
  353. }
  354. {
  355. advanced = memnew(CheckButton);
  356. advanced->set_text(TTR("Advanced"));
  357. advanced->set_toggle_mode(true);
  358. advanced->set_pressed(false);
  359. advanced->connect("toggled", callable_mp(this, &EditorLocaleDialog::_toggle_advanced));
  360. hb_filter->add_child(advanced);
  361. }
  362. vb->add_child(hb_filter);
  363. }
  364. {
  365. HBoxContainer *hb_lists = memnew(HBoxContainer);
  366. hb_lists->set_v_size_flags(Control::SIZE_EXPAND_FILL);
  367. {
  368. VBoxContainer *vb_lang_list = memnew(VBoxContainer);
  369. vb_lang_list->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  370. {
  371. Label *lang_lbl = memnew(Label);
  372. lang_lbl->set_text(TTR("Language:"));
  373. vb_lang_list->add_child(lang_lbl);
  374. }
  375. {
  376. lang_list = memnew(Tree);
  377. lang_list->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
  378. lang_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
  379. lang_list->connect("cell_selected", callable_mp(this, &EditorLocaleDialog::_item_selected));
  380. lang_list->set_columns(1);
  381. lang_list->connect("item_edited", callable_mp(this, &EditorLocaleDialog::_filter_lang_option_changed));
  382. vb_lang_list->add_child(lang_list);
  383. }
  384. hb_lists->add_child(vb_lang_list);
  385. }
  386. {
  387. vb_script_list = memnew(VBoxContainer);
  388. vb_script_list->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  389. {
  390. Label *script_lbl = memnew(Label);
  391. // TRANSLATORS: This is the label for a list of writing systems.
  392. script_lbl->set_text(TTR("Script:", "Locale"));
  393. vb_script_list->add_child(script_lbl);
  394. }
  395. {
  396. script_list = memnew(Tree);
  397. script_list->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
  398. script_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
  399. script_list->connect("cell_selected", callable_mp(this, &EditorLocaleDialog::_item_selected));
  400. script_list->set_columns(1);
  401. script_list->connect("item_edited", callable_mp(this, &EditorLocaleDialog::_filter_script_option_changed));
  402. vb_script_list->add_child(script_list);
  403. }
  404. hb_lists->add_child(vb_script_list);
  405. }
  406. {
  407. VBoxContainer *vb_cnt_list = memnew(VBoxContainer);
  408. vb_cnt_list->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  409. {
  410. Label *cnt_lbl = memnew(Label);
  411. cnt_lbl->set_text(TTR("Country:"));
  412. vb_cnt_list->add_child(cnt_lbl);
  413. }
  414. {
  415. cnt_list = memnew(Tree);
  416. cnt_list->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
  417. cnt_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
  418. cnt_list->connect("cell_selected", callable_mp(this, &EditorLocaleDialog::_item_selected));
  419. cnt_list->set_columns(1);
  420. cnt_list->connect("item_edited", callable_mp(this, &EditorLocaleDialog::_filter_cnt_option_changed));
  421. vb_cnt_list->add_child(cnt_list);
  422. }
  423. hb_lists->add_child(vb_cnt_list);
  424. }
  425. vb->add_child(hb_lists);
  426. }
  427. {
  428. hb_locale = memnew(HBoxContainer);
  429. hb_locale->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  430. {
  431. {
  432. VBoxContainer *vb_language = memnew(VBoxContainer);
  433. vb_language->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  434. {
  435. Label *language_lbl = memnew(Label);
  436. language_lbl->set_text(TTR("Language"));
  437. vb_language->add_child(language_lbl);
  438. }
  439. {
  440. lang_code = memnew(LineEdit);
  441. lang_code->set_max_length(3);
  442. lang_code->set_tooltip_text("Language");
  443. vb_language->add_child(lang_code);
  444. }
  445. hb_locale->add_child(vb_language);
  446. }
  447. {
  448. VBoxContainer *vb_script = memnew(VBoxContainer);
  449. vb_script->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  450. {
  451. Label *script_lbl = memnew(Label);
  452. // TRANSLATORS: This refers to a writing system.
  453. script_lbl->set_text(TTR("Script", "Locale"));
  454. vb_script->add_child(script_lbl);
  455. }
  456. {
  457. script_code = memnew(LineEdit);
  458. script_code->set_max_length(4);
  459. script_code->set_tooltip_text("Script");
  460. vb_script->add_child(script_code);
  461. }
  462. hb_locale->add_child(vb_script);
  463. }
  464. {
  465. VBoxContainer *vb_country = memnew(VBoxContainer);
  466. vb_country->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  467. {
  468. Label *country_lbl = memnew(Label);
  469. country_lbl->set_text(TTR("Country"));
  470. vb_country->add_child(country_lbl);
  471. }
  472. {
  473. country_code = memnew(LineEdit);
  474. country_code->set_max_length(2);
  475. country_code->set_tooltip_text("Country");
  476. vb_country->add_child(country_code);
  477. }
  478. hb_locale->add_child(vb_country);
  479. }
  480. {
  481. VBoxContainer *vb_variant = memnew(VBoxContainer);
  482. vb_variant->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  483. {
  484. Label *variant_lbl = memnew(Label);
  485. variant_lbl->set_text(TTR("Variant"));
  486. vb_variant->add_child(variant_lbl);
  487. }
  488. {
  489. variant_code = memnew(LineEdit);
  490. variant_code->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  491. variant_code->set_placeholder("Variant");
  492. variant_code->set_tooltip_text("Variant");
  493. vb_variant->add_child(variant_code);
  494. }
  495. hb_locale->add_child(vb_variant);
  496. }
  497. }
  498. vb->add_child(hb_locale);
  499. }
  500. add_child(vb);
  501. _update_tree();
  502. set_ok_button_text(TTR("Select"));
  503. }