Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/editor/translations/editor_locale_dialog.cpp
9896 views
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
31
#include "editor_locale_dialog.h"
32
33
#include "core/config/project_settings.h"
34
#include "core/string/translation_server.h"
35
#include "editor/editor_undo_redo_manager.h"
36
#include "editor/themes/editor_scale.h"
37
#include "scene/gui/check_button.h"
38
#include "scene/gui/line_edit.h"
39
#include "scene/gui/option_button.h"
40
#include "scene/gui/tree.h"
41
42
void EditorLocaleDialog::_notification(int p_what) {
43
if (p_what == NOTIFICATION_TRANSLATION_CHANGED) {
44
// TRANSLATORS: This is the label for a list of writing systems.
45
script_label1->set_text(TTR("Script:", "Locale"));
46
// TRANSLATORS: This refers to a writing system.
47
script_label2->set_text(TTR("Script", "Locale"));
48
49
script_list->set_accessibility_name(TTR("Script", "Locale"));
50
script_code->set_accessibility_name(TTR("Script", "Locale"));
51
}
52
}
53
54
void EditorLocaleDialog::_bind_methods() {
55
ADD_SIGNAL(MethodInfo("locale_selected", PropertyInfo(Variant::STRING, "locale")));
56
}
57
58
void EditorLocaleDialog::ok_pressed() {
59
if (edit_filters->is_pressed()) {
60
return; // Do not update, if in filter edit mode.
61
}
62
63
String locale;
64
if (lang_code->get_text().is_empty()) {
65
return; // Language code is required.
66
}
67
locale = lang_code->get_text();
68
69
if (!script_code->get_text().is_empty()) {
70
locale += "_" + script_code->get_text();
71
}
72
if (!country_code->get_text().is_empty()) {
73
locale += "_" + country_code->get_text();
74
}
75
if (!variant_code->get_text().is_empty()) {
76
locale += "_" + variant_code->get_text();
77
}
78
79
emit_signal(SNAME("locale_selected"), TranslationServer::get_singleton()->standardize_locale(locale));
80
hide();
81
}
82
83
void EditorLocaleDialog::_item_selected() {
84
if (updating_lists) {
85
return;
86
}
87
88
if (edit_filters->is_pressed()) {
89
return; // Do not update, if in filter edit mode.
90
}
91
92
TreeItem *l = lang_list->get_selected();
93
if (l) {
94
lang_code->set_text(l->get_metadata(0).operator String());
95
}
96
97
TreeItem *s = script_list->get_selected();
98
if (s) {
99
script_code->set_text(s->get_metadata(0).operator String());
100
}
101
102
TreeItem *c = cnt_list->get_selected();
103
if (c) {
104
country_code->set_text(c->get_metadata(0).operator String());
105
}
106
}
107
108
void EditorLocaleDialog::_toggle_advanced(bool p_checked) {
109
if (!p_checked) {
110
script_code->set_text("");
111
variant_code->set_text("");
112
}
113
_update_tree();
114
}
115
116
void EditorLocaleDialog::_post_popup() {
117
ConfirmationDialog::_post_popup();
118
119
if (!locale_set) {
120
lang_code->set_text("");
121
script_code->set_text("");
122
country_code->set_text("");
123
variant_code->set_text("");
124
}
125
edit_filters->set_pressed(false);
126
_update_tree();
127
}
128
129
void EditorLocaleDialog::_filter_lang_option_changed() {
130
TreeItem *t = lang_list->get_edited();
131
String lang = t->get_metadata(0);
132
bool checked = t->is_checked(0);
133
134
Variant prev;
135
Array f_lang_all;
136
137
if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/language_filter")) {
138
f_lang_all = GLOBAL_GET("internationalization/locale/language_filter");
139
prev = f_lang_all;
140
}
141
142
int l_idx = f_lang_all.find(lang);
143
144
if (checked) {
145
if (l_idx == -1) {
146
f_lang_all.append(lang);
147
}
148
} else {
149
if (l_idx != -1) {
150
f_lang_all.remove_at(l_idx);
151
}
152
}
153
154
f_lang_all.sort();
155
156
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
157
undo_redo->create_action(TTR("Changed Locale Language Filter"));
158
undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/language_filter", f_lang_all);
159
undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/language_filter", prev);
160
undo_redo->commit_action();
161
}
162
163
void EditorLocaleDialog::_filter_script_option_changed() {
164
TreeItem *t = script_list->get_edited();
165
String scr_code = t->get_metadata(0);
166
bool checked = t->is_checked(0);
167
168
Variant prev;
169
Array f_script_all;
170
171
if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/script_filter")) {
172
f_script_all = GLOBAL_GET("internationalization/locale/script_filter");
173
prev = f_script_all;
174
}
175
176
int l_idx = f_script_all.find(scr_code);
177
178
if (checked) {
179
if (l_idx == -1) {
180
f_script_all.append(scr_code);
181
}
182
} else {
183
if (l_idx != -1) {
184
f_script_all.remove_at(l_idx);
185
}
186
}
187
188
f_script_all.sort();
189
190
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
191
undo_redo->create_action(TTR("Changed Locale Script Filter"));
192
undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/script_filter", f_script_all);
193
undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/script_filter", prev);
194
undo_redo->commit_action();
195
}
196
197
void EditorLocaleDialog::_filter_cnt_option_changed() {
198
TreeItem *t = cnt_list->get_edited();
199
String cnt = t->get_metadata(0);
200
bool checked = t->is_checked(0);
201
202
Variant prev;
203
Array f_cnt_all;
204
205
if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/country_filter")) {
206
f_cnt_all = GLOBAL_GET("internationalization/locale/country_filter");
207
prev = f_cnt_all;
208
}
209
210
int l_idx = f_cnt_all.find(cnt);
211
212
if (checked) {
213
if (l_idx == -1) {
214
f_cnt_all.append(cnt);
215
}
216
} else {
217
if (l_idx != -1) {
218
f_cnt_all.remove_at(l_idx);
219
}
220
}
221
222
f_cnt_all.sort();
223
224
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
225
undo_redo->create_action(TTR("Changed Locale Country Filter"));
226
undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/country_filter", f_cnt_all);
227
undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/country_filter", prev);
228
undo_redo->commit_action();
229
}
230
231
void EditorLocaleDialog::_filter_mode_changed(int p_mode) {
232
int f_mode = filter_mode->get_selected_id();
233
Variant prev;
234
235
if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/locale_filter_mode")) {
236
prev = GLOBAL_GET("internationalization/locale/locale_filter_mode");
237
}
238
239
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
240
undo_redo->create_action(TTR("Changed Locale Filter Mode"));
241
undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/locale_filter_mode", f_mode);
242
undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/locale_filter_mode", prev);
243
undo_redo->commit_action();
244
245
_update_tree();
246
}
247
248
void EditorLocaleDialog::_edit_filters(bool p_checked) {
249
_update_tree();
250
}
251
252
void EditorLocaleDialog::_update_tree() {
253
updating_lists = true;
254
255
int filter = SHOW_ALL_LOCALES;
256
if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/locale_filter_mode")) {
257
filter = GLOBAL_GET_CACHED(int, "internationalization/locale/locale_filter_mode");
258
}
259
Array f_lang_all;
260
if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/language_filter")) {
261
f_lang_all = GLOBAL_GET("internationalization/locale/language_filter");
262
}
263
Array f_cnt_all;
264
if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/country_filter")) {
265
f_cnt_all = GLOBAL_GET("internationalization/locale/country_filter");
266
}
267
Array f_script_all;
268
if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/script_filter")) {
269
f_script_all = GLOBAL_GET("internationalization/locale/script_filter");
270
}
271
bool is_edit_mode = edit_filters->is_pressed();
272
273
filter_mode->select(filter);
274
275
// Hide text advanced edit and disable OK button if in filter edit mode.
276
advanced->set_visible(!is_edit_mode);
277
hb_locale->set_visible(!is_edit_mode && advanced->is_pressed());
278
vb_script_list->set_visible(advanced->is_pressed());
279
get_ok_button()->set_disabled(is_edit_mode);
280
281
// Update language list.
282
lang_list->clear();
283
TreeItem *l_root = lang_list->create_item(nullptr);
284
lang_list->set_hide_root(true);
285
286
Vector<String> languages = TranslationServer::get_singleton()->get_all_languages();
287
for (const String &E : languages) {
288
if (is_edit_mode || (filter == SHOW_ALL_LOCALES) || f_lang_all.has(E) || f_lang_all.is_empty()) {
289
const String &lang = TranslationServer::get_singleton()->get_language_name(E);
290
TreeItem *t = lang_list->create_item(l_root);
291
if (is_edit_mode) {
292
t->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
293
t->set_editable(0, true);
294
t->set_checked(0, f_lang_all.has(E));
295
} else if (lang_code->get_text() == E) {
296
t->select(0);
297
}
298
t->set_text(0, vformat("%s [%s]", lang, E));
299
t->set_metadata(0, E);
300
}
301
}
302
303
// Update script list.
304
script_list->clear();
305
TreeItem *s_root = script_list->create_item(nullptr);
306
script_list->set_hide_root(true);
307
308
if (!is_edit_mode) {
309
TreeItem *t = script_list->create_item(s_root);
310
t->set_text(0, TTRC("[Default]"));
311
t->set_metadata(0, "");
312
}
313
314
Vector<String> scripts = TranslationServer::get_singleton()->get_all_scripts();
315
for (const String &E : scripts) {
316
if (is_edit_mode || (filter == SHOW_ALL_LOCALES) || f_script_all.has(E) || f_script_all.is_empty()) {
317
const String &scr_code = TranslationServer::get_singleton()->get_script_name(E);
318
TreeItem *t = script_list->create_item(s_root);
319
if (is_edit_mode) {
320
t->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
321
t->set_editable(0, true);
322
t->set_checked(0, f_script_all.has(E));
323
} else if (script_code->get_text() == E) {
324
t->select(0);
325
}
326
t->set_text(0, vformat("%s [%s]", scr_code, E));
327
t->set_metadata(0, E);
328
}
329
}
330
331
// Update country list.
332
cnt_list->clear();
333
TreeItem *c_root = cnt_list->create_item(nullptr);
334
cnt_list->set_hide_root(true);
335
336
if (!is_edit_mode) {
337
TreeItem *t = cnt_list->create_item(c_root);
338
t->set_text(0, TTRC("[Default]"));
339
t->set_metadata(0, "");
340
}
341
342
Vector<String> countries = TranslationServer::get_singleton()->get_all_countries();
343
for (const String &E : countries) {
344
if (is_edit_mode || (filter == SHOW_ALL_LOCALES) || f_cnt_all.has(E) || f_cnt_all.is_empty()) {
345
const String &cnt = TranslationServer::get_singleton()->get_country_name(E);
346
TreeItem *t = cnt_list->create_item(c_root);
347
if (is_edit_mode) {
348
t->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
349
t->set_editable(0, true);
350
t->set_checked(0, f_cnt_all.has(E));
351
} else if (country_code->get_text() == E) {
352
t->select(0);
353
}
354
t->set_text(0, vformat("%s [%s]", cnt, E));
355
t->set_metadata(0, E);
356
}
357
}
358
updating_lists = false;
359
}
360
361
void EditorLocaleDialog::set_locale(const String &p_locale) {
362
const String &locale = TranslationServer::get_singleton()->standardize_locale(p_locale);
363
if (locale.is_empty()) {
364
locale_set = false;
365
366
lang_code->set_text("");
367
script_code->set_text("");
368
country_code->set_text("");
369
variant_code->set_text("");
370
} else {
371
locale_set = true;
372
373
Vector<String> locale_elements = p_locale.split("_");
374
lang_code->set_text(locale_elements[0]);
375
if (locale_elements.size() >= 2) {
376
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])) {
377
script_code->set_text(locale_elements[1]);
378
advanced->set_pressed(true);
379
}
380
if (locale_elements[1].length() == 2 && is_ascii_upper_case(locale_elements[1][0]) && is_ascii_upper_case(locale_elements[1][1])) {
381
country_code->set_text(locale_elements[1]);
382
}
383
}
384
if (locale_elements.size() >= 3) {
385
if (locale_elements[2].length() == 2 && is_ascii_upper_case(locale_elements[2][0]) && is_ascii_upper_case(locale_elements[2][1])) {
386
country_code->set_text(locale_elements[2]);
387
} else {
388
variant_code->set_text(locale_elements[2].to_lower());
389
advanced->set_pressed(true);
390
}
391
}
392
if (locale_elements.size() >= 4) {
393
variant_code->set_text(locale_elements[3].to_lower());
394
advanced->set_pressed(true);
395
}
396
}
397
}
398
399
void EditorLocaleDialog::popup_locale_dialog() {
400
popup_centered_clamped(Size2(1050, 700) * EDSCALE, 0.8);
401
}
402
403
EditorLocaleDialog::EditorLocaleDialog() {
404
set_title(TTRC("Select a Locale"));
405
406
VBoxContainer *vb = memnew(VBoxContainer);
407
{
408
HBoxContainer *hb_filter = memnew(HBoxContainer);
409
{
410
filter_mode = memnew(OptionButton);
411
filter_mode->set_accessibility_name(TTRC("Locale Filter"));
412
filter_mode->add_item(TTRC("Show All Locales"), SHOW_ALL_LOCALES);
413
filter_mode->set_h_size_flags(Control::SIZE_EXPAND_FILL);
414
filter_mode->add_item(TTRC("Show Selected Locales Only"), SHOW_ONLY_SELECTED_LOCALES);
415
filter_mode->select(0);
416
filter_mode->connect(SceneStringName(item_selected), callable_mp(this, &EditorLocaleDialog::_filter_mode_changed));
417
hb_filter->add_child(filter_mode);
418
}
419
{
420
edit_filters = memnew(CheckButton);
421
edit_filters->set_text(TTRC("Edit Filters"));
422
edit_filters->set_toggle_mode(true);
423
edit_filters->set_pressed(false);
424
edit_filters->connect(SceneStringName(toggled), callable_mp(this, &EditorLocaleDialog::_edit_filters));
425
hb_filter->add_child(edit_filters);
426
}
427
{
428
advanced = memnew(CheckButton);
429
advanced->set_text(TTRC("Advanced"));
430
advanced->set_toggle_mode(true);
431
advanced->set_pressed(false);
432
advanced->connect(SceneStringName(toggled), callable_mp(this, &EditorLocaleDialog::_toggle_advanced));
433
hb_filter->add_child(advanced);
434
}
435
vb->add_child(hb_filter);
436
}
437
{
438
HBoxContainer *hb_lists = memnew(HBoxContainer);
439
hb_lists->set_v_size_flags(Control::SIZE_EXPAND_FILL);
440
{
441
VBoxContainer *vb_lang_list = memnew(VBoxContainer);
442
vb_lang_list->set_h_size_flags(Control::SIZE_EXPAND_FILL);
443
{
444
Label *lang_lbl = memnew(Label);
445
lang_lbl->set_text(TTRC("Language:"));
446
vb_lang_list->add_child(lang_lbl);
447
}
448
{
449
lang_list = memnew(Tree);
450
lang_list->set_accessibility_name(TTRC("Language:"));
451
lang_list->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
452
lang_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
453
lang_list->connect("cell_selected", callable_mp(this, &EditorLocaleDialog::_item_selected));
454
lang_list->set_columns(1);
455
lang_list->connect("item_edited", callable_mp(this, &EditorLocaleDialog::_filter_lang_option_changed));
456
vb_lang_list->add_child(lang_list);
457
}
458
hb_lists->add_child(vb_lang_list);
459
}
460
{
461
vb_script_list = memnew(VBoxContainer);
462
vb_script_list->set_h_size_flags(Control::SIZE_EXPAND_FILL);
463
{
464
script_label1 = memnew(Label);
465
script_label1->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
466
vb_script_list->add_child(script_label1);
467
}
468
{
469
script_list = memnew(Tree);
470
script_list->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
471
script_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
472
script_list->connect("cell_selected", callable_mp(this, &EditorLocaleDialog::_item_selected));
473
script_list->set_columns(1);
474
script_list->connect("item_edited", callable_mp(this, &EditorLocaleDialog::_filter_script_option_changed));
475
vb_script_list->add_child(script_list);
476
}
477
hb_lists->add_child(vb_script_list);
478
}
479
{
480
VBoxContainer *vb_cnt_list = memnew(VBoxContainer);
481
vb_cnt_list->set_h_size_flags(Control::SIZE_EXPAND_FILL);
482
{
483
Label *cnt_lbl = memnew(Label);
484
cnt_lbl->set_text(TTRC("Country:"));
485
vb_cnt_list->add_child(cnt_lbl);
486
}
487
{
488
cnt_list = memnew(Tree);
489
cnt_list->set_accessibility_name(TTRC("Country:"));
490
cnt_list->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
491
cnt_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
492
cnt_list->connect("cell_selected", callable_mp(this, &EditorLocaleDialog::_item_selected));
493
cnt_list->set_columns(1);
494
cnt_list->connect("item_edited", callable_mp(this, &EditorLocaleDialog::_filter_cnt_option_changed));
495
vb_cnt_list->add_child(cnt_list);
496
}
497
hb_lists->add_child(vb_cnt_list);
498
}
499
vb->add_child(hb_lists);
500
}
501
{
502
hb_locale = memnew(HBoxContainer);
503
hb_locale->set_h_size_flags(Control::SIZE_EXPAND_FILL);
504
{
505
{
506
VBoxContainer *vb_language = memnew(VBoxContainer);
507
vb_language->set_h_size_flags(Control::SIZE_EXPAND_FILL);
508
{
509
Label *language_lbl = memnew(Label);
510
language_lbl->set_text(TTRC("Language"));
511
vb_language->add_child(language_lbl);
512
}
513
{
514
lang_code = memnew(LineEdit);
515
lang_code->set_max_length(3);
516
lang_code->set_accessibility_name("Language");
517
vb_language->add_child(lang_code);
518
}
519
hb_locale->add_child(vb_language);
520
}
521
{
522
VBoxContainer *vb_script = memnew(VBoxContainer);
523
vb_script->set_h_size_flags(Control::SIZE_EXPAND_FILL);
524
{
525
script_label2 = memnew(Label);
526
script_label2->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
527
vb_script->add_child(script_label2);
528
}
529
{
530
script_code = memnew(LineEdit);
531
script_code->set_max_length(4);
532
vb_script->add_child(script_code);
533
}
534
hb_locale->add_child(vb_script);
535
}
536
{
537
VBoxContainer *vb_country = memnew(VBoxContainer);
538
vb_country->set_h_size_flags(Control::SIZE_EXPAND_FILL);
539
{
540
Label *country_lbl = memnew(Label);
541
country_lbl->set_text(TTRC("Country"));
542
vb_country->add_child(country_lbl);
543
}
544
{
545
country_code = memnew(LineEdit);
546
country_code->set_max_length(2);
547
country_code->set_tooltip_text("Country");
548
vb_country->add_child(country_code);
549
}
550
hb_locale->add_child(vb_country);
551
}
552
{
553
VBoxContainer *vb_variant = memnew(VBoxContainer);
554
vb_variant->set_h_size_flags(Control::SIZE_EXPAND_FILL);
555
{
556
Label *variant_lbl = memnew(Label);
557
variant_lbl->set_text(TTRC("Variant"));
558
vb_variant->add_child(variant_lbl);
559
}
560
{
561
variant_code = memnew(LineEdit);
562
variant_code->set_h_size_flags(Control::SIZE_EXPAND_FILL);
563
variant_code->set_placeholder("Variant");
564
variant_code->set_accessibility_name("Variant");
565
vb_variant->add_child(variant_code);
566
}
567
hb_locale->add_child(vb_variant);
568
}
569
}
570
vb->add_child(hb_locale);
571
}
572
add_child(vb);
573
_update_tree();
574
575
set_ok_button_text(TTRC("Select"));
576
}
577
578