2023-01-05 13:25:55 +01:00
/**************************************************************************/
/* localization_editor.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
2020-07-11 00:52:52 +02:00
# include "localization_editor.h"
2022-02-12 02:46:22 +01:00
# include "core/config/project_settings.h"
2020-11-07 23:33:38 +01:00
# include "core/string/translation.h"
2022-02-12 02:46:22 +01:00
# include "editor/editor_translation_parser.h"
2022-03-25 18:06:46 +01:00
# include "editor/editor_undo_redo_manager.h"
2022-01-02 18:56:33 +01:00
# include "editor/filesystem_dock.h"
2023-04-07 18:59:49 +02:00
# include "editor/gui/editor_file_dialog.h"
2022-02-12 02:46:22 +01:00
# include "editor/pot_generator.h"
2024-01-15 13:14:55 +01:00
# include "editor/themes/editor_scale.h"
2020-07-11 00:52:52 +02:00
# include "scene/gui/control.h"
void LocalizationEditor : : _notification ( int p_what ) {
2022-02-16 03:44:22 +01:00
switch ( p_what ) {
case NOTIFICATION_ENTER_TREE : {
2021-09-18 09:33:18 +02:00
translation_list - > connect ( " button_clicked " , callable_mp ( this , & LocalizationEditor : : _translation_delete ) ) ;
translation_pot_list - > connect ( " button_clicked " , callable_mp ( this , & LocalizationEditor : : _pot_delete ) ) ;
2020-07-11 00:52:52 +02:00
2022-02-16 03:44:22 +01:00
List < String > tfn ;
ResourceLoader : : get_recognized_extensions_for_type ( " Translation " , & tfn ) ;
for ( const String & E : tfn ) {
translation_file_open - > add_filter ( " *. " + E ) ;
}
2020-07-11 00:52:52 +02:00
2022-02-16 03:44:22 +01:00
List < String > rfn ;
ResourceLoader : : get_recognized_extensions_for_type ( " Resource " , & rfn ) ;
for ( const String & E : rfn ) {
translation_res_file_open_dialog - > add_filter ( " *. " + E ) ;
translation_res_option_file_open_dialog - > add_filter ( " *. " + E ) ;
}
2020-07-11 00:52:52 +02:00
2022-02-16 03:44:22 +01:00
_update_pot_file_extensions ( ) ;
pot_generate_dialog - > add_filter ( " *.pot " ) ;
} break ;
2020-07-11 00:52:52 +02:00
}
}
void LocalizationEditor : : add_translation ( const String & p_translation ) {
2020-12-29 09:26:45 +01:00
PackedStringArray translations ;
translations . push_back ( p_translation ) ;
_translation_add ( translations ) ;
2020-07-11 00:52:52 +02:00
}
2020-12-29 09:26:45 +01:00
void LocalizationEditor : : _translation_add ( const PackedStringArray & p_paths ) {
2022-10-18 16:43:37 +02:00
PackedStringArray translations = GLOBAL_GET ( " internationalization/locale/translations " ) ;
2020-12-29 09:26:45 +01:00
for ( int i = 0 ; i < p_paths . size ( ) ; i + + ) {
if ( ! translations . has ( p_paths [ i ] ) ) {
// Don't add duplicate translation paths.
translations . push_back ( p_paths [ i ] ) ;
}
2020-07-11 00:52:52 +02:00
}
2022-12-23 23:53:16 +01:00
EditorUndoRedoManager * undo_redo = EditorUndoRedoManager : : get_singleton ( ) ;
2020-12-29 09:26:45 +01:00
undo_redo - > create_action ( vformat ( TTR ( " Add %d Translations " ) , p_paths . size ( ) ) ) ;
2021-02-17 17:44:49 +01:00
undo_redo - > add_do_property ( ProjectSettings : : get_singleton ( ) , " internationalization/locale/translations " , translations ) ;
2022-10-18 16:43:37 +02:00
undo_redo - > add_undo_property ( ProjectSettings : : get_singleton ( ) , " internationalization/locale/translations " , GLOBAL_GET ( " internationalization/locale/translations " ) ) ;
2020-07-11 00:52:52 +02:00
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_file_open ( ) {
2020-07-11 18:45:19 +02:00
translation_file_open - > popup_file_dialog ( ) ;
2020-07-11 00:52:52 +02:00
}
2021-09-18 09:33:18 +02:00
void LocalizationEditor : : _translation_delete ( Object * p_item , int p_column , int p_button , MouseButton p_mouse_button ) {
if ( p_mouse_button ! = MouseButton : : LEFT ) {
return ;
}
2020-07-11 00:52:52 +02:00
TreeItem * ti = Object : : cast_to < TreeItem > ( p_item ) ;
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL ( ti ) ;
2020-07-11 00:52:52 +02:00
int idx = ti - > get_metadata ( 0 ) ;
2022-10-18 16:43:37 +02:00
PackedStringArray translations = GLOBAL_GET ( " internationalization/locale/translations " ) ;
2020-07-11 00:52:52 +02:00
ERR_FAIL_INDEX ( idx , translations . size ( ) ) ;
2021-07-04 00:17:03 +02:00
translations . remove_at ( idx ) ;
2020-07-11 00:52:52 +02:00
2022-12-23 23:53:16 +01:00
EditorUndoRedoManager * undo_redo = EditorUndoRedoManager : : get_singleton ( ) ;
2020-07-11 00:52:52 +02:00
undo_redo - > create_action ( TTR ( " Remove Translation " ) ) ;
2021-02-17 17:44:49 +01:00
undo_redo - > add_do_property ( ProjectSettings : : get_singleton ( ) , " internationalization/locale/translations " , translations ) ;
2022-10-18 16:43:37 +02:00
undo_redo - > add_undo_property ( ProjectSettings : : get_singleton ( ) , " internationalization/locale/translations " , GLOBAL_GET ( " internationalization/locale/translations " ) ) ;
2020-07-11 00:52:52 +02:00
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_res_file_open ( ) {
2020-07-11 18:45:19 +02:00
translation_res_file_open_dialog - > popup_file_dialog ( ) ;
2020-07-11 00:52:52 +02:00
}
2020-12-29 09:26:45 +01:00
void LocalizationEditor : : _translation_res_add ( const PackedStringArray & p_paths ) {
2020-07-11 00:52:52 +02:00
Variant prev ;
Dictionary remaps ;
2021-02-17 17:44:49 +01:00
if ( ProjectSettings : : get_singleton ( ) - > has_setting ( " internationalization/locale/translation_remaps " ) ) {
2022-10-18 16:43:37 +02:00
remaps = GLOBAL_GET ( " internationalization/locale/translation_remaps " ) ;
2020-07-11 00:52:52 +02:00
prev = remaps ;
}
2020-12-29 09:26:45 +01:00
for ( int i = 0 ; i < p_paths . size ( ) ; i + + ) {
if ( ! remaps . has ( p_paths [ i ] ) ) {
// Don't overwrite with an empty remap array if an array already exists for the given path.
remaps [ p_paths [ i ] ] = PackedStringArray ( ) ;
}
2020-07-11 00:52:52 +02:00
}
2022-12-23 23:53:16 +01:00
EditorUndoRedoManager * undo_redo = EditorUndoRedoManager : : get_singleton ( ) ;
2020-12-29 09:26:45 +01:00
undo_redo - > create_action ( vformat ( TTR ( " Translation Resource Remap: Add %d Path(s) " ) , p_paths . size ( ) ) ) ;
2021-02-17 17:44:49 +01:00
undo_redo - > add_do_property ( ProjectSettings : : get_singleton ( ) , " internationalization/locale/translation_remaps " , remaps ) ;
undo_redo - > add_undo_property ( ProjectSettings : : get_singleton ( ) , " internationalization/locale/translation_remaps " , prev ) ;
2020-07-11 00:52:52 +02:00
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_res_option_file_open ( ) {
2020-07-11 18:45:19 +02:00
translation_res_option_file_open_dialog - > popup_file_dialog ( ) ;
2020-07-11 00:52:52 +02:00
}
2020-12-29 09:26:45 +01:00
void LocalizationEditor : : _translation_res_option_add ( const PackedStringArray & p_paths ) {
2021-02-17 17:44:49 +01:00
ERR_FAIL_COND ( ! ProjectSettings : : get_singleton ( ) - > has_setting ( " internationalization/locale/translation_remaps " ) ) ;
2020-07-11 00:52:52 +02:00
2022-10-18 16:43:37 +02:00
Dictionary remaps = GLOBAL_GET ( " internationalization/locale/translation_remaps " ) ;
2020-07-11 00:52:52 +02:00
TreeItem * k = translation_remap - > get_selected ( ) ;
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL ( k ) ;
2020-07-11 00:52:52 +02:00
String key = k - > get_metadata ( 0 ) ;
ERR_FAIL_COND ( ! remaps . has ( key ) ) ;
PackedStringArray r = remaps [ key ] ;
2020-12-29 09:26:45 +01:00
for ( int i = 0 ; i < p_paths . size ( ) ; i + + ) {
r . push_back ( p_paths [ i ] + " : " + " en " ) ;
}
2020-07-11 00:52:52 +02:00
remaps [ key ] = r ;
2022-12-23 23:53:16 +01:00
EditorUndoRedoManager * undo_redo = EditorUndoRedoManager : : get_singleton ( ) ;
2020-12-29 09:26:45 +01:00
undo_redo - > create_action ( vformat ( TTR ( " Translation Resource Remap: Add %d Remap(s) " ) , p_paths . size ( ) ) ) ;
2021-02-17 17:44:49 +01:00
undo_redo - > add_do_property ( ProjectSettings : : get_singleton ( ) , " internationalization/locale/translation_remaps " , remaps ) ;
2022-10-18 16:43:37 +02:00
undo_redo - > add_undo_property ( ProjectSettings : : get_singleton ( ) , " internationalization/locale/translation_remaps " , GLOBAL_GET ( " internationalization/locale/translation_remaps " ) ) ;
2020-07-11 00:52:52 +02:00
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_res_select ( ) {
if ( updating_translations ) {
return ;
}
2023-12-18 15:46:56 +01:00
callable_mp ( this , & LocalizationEditor : : update_translations ) . call_deferred ( ) ;
2020-07-11 00:52:52 +02:00
}
2021-09-23 13:08:50 +02:00
void LocalizationEditor : : _translation_res_option_popup ( bool p_arrow_clicked ) {
TreeItem * ed = translation_remap_options - > get_edited ( ) ;
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL ( ed ) ;
2021-09-23 13:08:50 +02:00
2022-08-29 15:55:49 +02:00
locale_select - > set_locale ( ed - > get_tooltip_text ( 1 ) ) ;
2021-09-23 13:08:50 +02:00
locale_select - > popup_locale_dialog ( ) ;
}
void LocalizationEditor : : _translation_res_option_selected ( const String & p_locale ) {
TreeItem * ed = translation_remap_options - > get_edited ( ) ;
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL ( ed ) ;
2021-09-23 13:08:50 +02:00
ed - > set_text ( 1 , TranslationServer : : get_singleton ( ) - > get_locale_name ( p_locale ) ) ;
2022-08-29 15:55:49 +02:00
ed - > set_tooltip_text ( 1 , p_locale ) ;
2021-09-23 13:08:50 +02:00
LocalizationEditor : : _translation_res_option_changed ( ) ;
}
2020-07-11 00:52:52 +02:00
void LocalizationEditor : : _translation_res_option_changed ( ) {
if ( updating_translations ) {
return ;
}
2021-02-17 17:44:49 +01:00
if ( ! ProjectSettings : : get_singleton ( ) - > has_setting ( " internationalization/locale/translation_remaps " ) ) {
2020-07-11 00:52:52 +02:00
return ;
}
2022-10-18 16:43:37 +02:00
Dictionary remaps = GLOBAL_GET ( " internationalization/locale/translation_remaps " ) ;
2020-07-11 00:52:52 +02:00
TreeItem * k = translation_remap - > get_selected ( ) ;
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL ( k ) ;
2020-07-11 00:52:52 +02:00
TreeItem * ed = translation_remap_options - > get_edited ( ) ;
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL ( ed ) ;
2020-07-11 00:52:52 +02:00
String key = k - > get_metadata ( 0 ) ;
int idx = ed - > get_metadata ( 0 ) ;
String path = ed - > get_metadata ( 1 ) ;
2022-08-29 15:55:49 +02:00
String locale = ed - > get_tooltip_text ( 1 ) ;
2020-07-11 00:52:52 +02:00
ERR_FAIL_COND ( ! remaps . has ( key ) ) ;
PackedStringArray r = remaps [ key ] ;
2021-09-23 13:08:50 +02:00
r . set ( idx , path + " : " + locale ) ;
2020-07-11 00:52:52 +02:00
remaps [ key ] = r ;
updating_translations = true ;
2022-08-29 12:10:32 +02:00
2022-12-23 23:53:16 +01:00
EditorUndoRedoManager * undo_redo = EditorUndoRedoManager : : get_singleton ( ) ;
2020-07-11 00:52:52 +02:00
undo_redo - > create_action ( TTR ( " Change Resource Remap Language " ) ) ;
2021-02-17 17:44:49 +01:00
undo_redo - > add_do_property ( ProjectSettings : : get_singleton ( ) , " internationalization/locale/translation_remaps " , remaps ) ;
2022-10-18 16:43:37 +02:00
undo_redo - > add_undo_property ( ProjectSettings : : get_singleton ( ) , " internationalization/locale/translation_remaps " , GLOBAL_GET ( " internationalization/locale/translation_remaps " ) ) ;
2020-07-11 00:52:52 +02:00
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 ( ) ;
updating_translations = false ;
}
2021-09-18 09:33:18 +02:00
void LocalizationEditor : : _translation_res_delete ( Object * p_item , int p_column , int p_button , MouseButton p_mouse_button ) {
2020-07-11 00:52:52 +02:00
if ( updating_translations ) {
return ;
}
2021-09-18 09:33:18 +02:00
if ( p_mouse_button ! = MouseButton : : LEFT ) {
return ;
}
2021-02-17 17:44:49 +01:00
if ( ! ProjectSettings : : get_singleton ( ) - > has_setting ( " internationalization/locale/translation_remaps " ) ) {
2020-07-11 00:52:52 +02:00
return ;
}
2022-10-18 16:43:37 +02:00
Dictionary remaps = GLOBAL_GET ( " internationalization/locale/translation_remaps " ) ;
2020-07-11 00:52:52 +02:00
TreeItem * k = Object : : cast_to < TreeItem > ( p_item ) ;
String key = k - > get_metadata ( 0 ) ;
ERR_FAIL_COND ( ! remaps . has ( key ) ) ;
remaps . erase ( key ) ;
2022-12-23 23:53:16 +01:00
EditorUndoRedoManager * undo_redo = EditorUndoRedoManager : : get_singleton ( ) ;
2020-07-11 00:52:52 +02:00
undo_redo - > create_action ( TTR ( " Remove Resource Remap " ) ) ;
2021-02-17 17:44:49 +01:00
undo_redo - > add_do_property ( ProjectSettings : : get_singleton ( ) , " internationalization/locale/translation_remaps " , remaps ) ;
2022-10-18 16:43:37 +02:00
undo_redo - > add_undo_property ( ProjectSettings : : get_singleton ( ) , " internationalization/locale/translation_remaps " , GLOBAL_GET ( " internationalization/locale/translation_remaps " ) ) ;
2020-07-11 00:52:52 +02:00
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 ( ) ;
}
2021-09-18 09:33:18 +02:00
void LocalizationEditor : : _translation_res_option_delete ( Object * p_item , int p_column , int p_button , MouseButton p_mouse_button ) {
2020-07-11 00:52:52 +02:00
if ( updating_translations ) {
return ;
}
2021-09-18 09:33:18 +02:00
if ( p_mouse_button ! = MouseButton : : LEFT ) {
return ;
}
2021-02-17 17:44:49 +01:00
if ( ! ProjectSettings : : get_singleton ( ) - > has_setting ( " internationalization/locale/translation_remaps " ) ) {
2020-07-11 00:52:52 +02:00
return ;
}
2022-10-18 16:43:37 +02:00
Dictionary remaps = GLOBAL_GET ( " internationalization/locale/translation_remaps " ) ;
2020-07-11 00:52:52 +02:00
TreeItem * k = translation_remap - > get_selected ( ) ;
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL ( k ) ;
2020-07-11 00:52:52 +02:00
TreeItem * ed = Object : : cast_to < TreeItem > ( p_item ) ;
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL ( ed ) ;
2020-07-11 00:52:52 +02:00
String key = k - > get_metadata ( 0 ) ;
int idx = ed - > get_metadata ( 0 ) ;
ERR_FAIL_COND ( ! remaps . has ( key ) ) ;
PackedStringArray r = remaps [ key ] ;
ERR_FAIL_INDEX ( idx , r . size ( ) ) ;
2021-07-04 00:17:03 +02:00
r . remove_at ( idx ) ;
2020-07-11 00:52:52 +02:00
remaps [ key ] = r ;
2022-12-23 23:53:16 +01:00
EditorUndoRedoManager * undo_redo = EditorUndoRedoManager : : get_singleton ( ) ;
2020-07-11 00:52:52 +02:00
undo_redo - > create_action ( TTR ( " Remove Resource Remap Option " ) ) ;
2021-02-17 17:44:49 +01:00
undo_redo - > add_do_property ( ProjectSettings : : get_singleton ( ) , " internationalization/locale/translation_remaps " , remaps ) ;
2022-10-18 16:43:37 +02:00
undo_redo - > add_undo_property ( ProjectSettings : : get_singleton ( ) , " internationalization/locale/translation_remaps " , GLOBAL_GET ( " internationalization/locale/translation_remaps " ) ) ;
2020-07-11 00:52:52 +02:00
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 ( ) ;
}
2020-12-29 09:26:45 +01:00
void LocalizationEditor : : _pot_add ( const PackedStringArray & p_paths ) {
2022-10-18 16:43:37 +02:00
PackedStringArray pot_translations = GLOBAL_GET ( " internationalization/locale/translations_pot_files " ) ;
2020-12-29 09:26:45 +01:00
for ( int i = 0 ; i < p_paths . size ( ) ; i + + ) {
2021-08-01 00:35:46 +02:00
if ( ! pot_translations . has ( p_paths [ i ] ) ) {
pot_translations . push_back ( p_paths [ i ] ) ;
2020-07-11 00:52:52 +02:00
}
}
2022-12-23 23:53:16 +01:00
EditorUndoRedoManager * undo_redo = EditorUndoRedoManager : : get_singleton ( ) ;
2020-12-29 09:26:45 +01:00
undo_redo - > create_action ( vformat ( TTR ( " Add %d file(s) for POT generation " ) , p_paths . size ( ) ) ) ;
2021-02-17 17:44:49 +01:00
undo_redo - > add_do_property ( ProjectSettings : : get_singleton ( ) , " internationalization/locale/translations_pot_files " , pot_translations ) ;
2022-10-18 16:43:37 +02:00
undo_redo - > add_undo_property ( ProjectSettings : : get_singleton ( ) , " internationalization/locale/translations_pot_files " , GLOBAL_GET ( " internationalization/locale/translations_pot_files " ) ) ;
2020-07-11 00:52:52 +02:00
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 ( ) ;
}
2021-09-18 09:33:18 +02:00
void LocalizationEditor : : _pot_delete ( Object * p_item , int p_column , int p_button , MouseButton p_mouse_button ) {
if ( p_mouse_button ! = MouseButton : : LEFT ) {
return ;
}
2020-07-11 00:52:52 +02:00
TreeItem * ti = Object : : cast_to < TreeItem > ( p_item ) ;
2023-09-09 17:24:40 +02:00
ERR_FAIL_NULL ( ti ) ;
2020-07-11 00:52:52 +02:00
int idx = ti - > get_metadata ( 0 ) ;
2022-10-18 16:43:37 +02:00
PackedStringArray pot_translations = GLOBAL_GET ( " internationalization/locale/translations_pot_files " ) ;
2020-07-11 00:52:52 +02:00
ERR_FAIL_INDEX ( idx , pot_translations . size ( ) ) ;
2021-07-04 00:17:03 +02:00
pot_translations . remove_at ( idx ) ;
2020-07-11 00:52:52 +02:00
2022-12-23 23:53:16 +01:00
EditorUndoRedoManager * undo_redo = EditorUndoRedoManager : : get_singleton ( ) ;
2020-07-11 00:52:52 +02:00
undo_redo - > create_action ( TTR ( " Remove file from POT generation " ) ) ;
2021-02-17 17:44:49 +01:00
undo_redo - > add_do_property ( ProjectSettings : : get_singleton ( ) , " internationalization/locale/translations_pot_files " , pot_translations ) ;
2022-10-18 16:43:37 +02:00
undo_redo - > add_undo_property ( ProjectSettings : : get_singleton ( ) , " internationalization/locale/translations_pot_files " , GLOBAL_GET ( " internationalization/locale/translations_pot_files " ) ) ;
2020-07-11 00:52:52 +02:00
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_file_open ( ) {
2020-07-11 18:45:19 +02:00
pot_file_open_dialog - > popup_file_dialog ( ) ;
2020-07-11 00:52:52 +02:00
}
void LocalizationEditor : : _pot_generate_open ( ) {
2020-07-11 18:45:19 +02:00
pot_generate_dialog - > popup_file_dialog ( ) ;
2020-07-11 00:52:52 +02:00
}
void LocalizationEditor : : _pot_generate ( const String & p_file ) {
POTGenerator : : get_singleton ( ) - > generate_pot ( p_file ) ;
}
void LocalizationEditor : : _update_pot_file_extensions ( ) {
pot_file_open_dialog - > clear_filters ( ) ;
List < String > translation_parse_file_extensions ;
EditorTranslationParser : : get_singleton ( ) - > get_recognized_extensions ( & translation_parse_file_extensions ) ;
2021-07-24 15:46:25 +02:00
for ( const String & E : translation_parse_file_extensions ) {
2021-07-16 05:45:57 +02:00
pot_file_open_dialog - > add_filter ( " *. " + E ) ;
2020-07-11 00:52:52 +02:00
}
}
2022-01-02 18:56:33 +01:00
void LocalizationEditor : : connect_filesystem_dock_signals ( FileSystemDock * p_fs_dock ) {
p_fs_dock - > connect ( " files_moved " , callable_mp ( this , & LocalizationEditor : : _filesystem_files_moved ) ) ;
2022-01-04 17:23:35 +01:00
p_fs_dock - > connect ( " file_removed " , callable_mp ( this , & LocalizationEditor : : _filesystem_file_removed ) ) ;
2022-01-02 18:56:33 +01:00
}
void LocalizationEditor : : _filesystem_files_moved ( const String & p_old_file , const String & p_new_file ) {
// Update remaps if the moved file is a part of them.
Dictionary remaps ;
bool remaps_changed = false ;
if ( ProjectSettings : : get_singleton ( ) - > has_setting ( " internationalization/locale/translation_remaps " ) ) {
2022-10-18 16:43:37 +02:00
remaps = GLOBAL_GET ( " internationalization/locale/translation_remaps " ) ;
2022-01-02 18:56:33 +01:00
}
// Check for the keys.
if ( remaps . has ( p_old_file ) ) {
PackedStringArray remapped_files = remaps [ p_old_file ] ;
remaps . erase ( p_old_file ) ;
remaps [ p_new_file ] = remapped_files ;
remaps_changed = true ;
print_verbose ( vformat ( " Changed remap key \" %s \" to \" %s \" due to a moved file. " , p_old_file , p_new_file ) ) ;
}
// Check for the Array elements of the values.
Array remap_keys = remaps . keys ( ) ;
for ( int i = 0 ; i < remap_keys . size ( ) ; i + + ) {
PackedStringArray remapped_files = remaps [ remap_keys [ i ] ] ;
bool remapped_files_updated = false ;
for ( int j = 0 ; j < remapped_files . size ( ) ; j + + ) {
2022-01-04 17:23:35 +01:00
int splitter_pos = remapped_files [ j ] . rfind ( " : " ) ;
2022-01-02 18:56:33 +01:00
String res_path = remapped_files [ j ] . substr ( 0 , splitter_pos ) ;
if ( res_path = = p_old_file ) {
String locale_name = remapped_files [ j ] . substr ( splitter_pos + 1 ) ;
// Replace the element at that index.
remapped_files . insert ( j , p_new_file + " : " + locale_name ) ;
remapped_files . remove_at ( j + 1 ) ;
remaps_changed = true ;
remapped_files_updated = true ;
print_verbose ( vformat ( " Changed remap value \" %s \" to \" %s \" of key \" %s \" due to a moved file. " , res_path + " : " + locale_name , remapped_files [ j ] , remap_keys [ i ] ) ) ;
}
}
if ( remapped_files_updated ) {
remaps [ remap_keys [ i ] ] = remapped_files ;
}
}
if ( remaps_changed ) {
ProjectSettings : : get_singleton ( ) - > set_setting ( " internationalization/locale/translation_remaps " , remaps ) ;
update_translations ( ) ;
emit_signal ( " localization_changed " ) ;
}
}
2022-01-04 17:23:35 +01:00
void LocalizationEditor : : _filesystem_file_removed ( const String & p_file ) {
// Check if the remaps are affected.
Dictionary remaps ;
if ( ProjectSettings : : get_singleton ( ) - > has_setting ( " internationalization/locale/translation_remaps " ) ) {
2022-10-18 16:43:37 +02:00
remaps = GLOBAL_GET ( " internationalization/locale/translation_remaps " ) ;
2022-01-04 17:23:35 +01:00
}
bool remaps_changed = remaps . has ( p_file ) ;
if ( ! remaps_changed ) {
Array remap_keys = remaps . keys ( ) ;
for ( int i = 0 ; i < remap_keys . size ( ) & & ! remaps_changed ; i + + ) {
PackedStringArray remapped_files = remaps [ remap_keys [ i ] ] ;
for ( int j = 0 ; j < remapped_files . size ( ) & & ! remaps_changed ; j + + ) {
int splitter_pos = remapped_files [ j ] . rfind ( " : " ) ;
String res_path = remapped_files [ j ] . substr ( 0 , splitter_pos ) ;
remaps_changed = p_file = = res_path ;
if ( remaps_changed ) {
print_verbose ( vformat ( " Remap value \" %s \" of key \" %s \" has been removed from the file system. " , remapped_files [ j ] , remap_keys [ i ] ) ) ;
}
}
}
} else {
print_verbose ( vformat ( " Remap key \" %s \" has been removed from the file system. " , p_file ) ) ;
}
if ( remaps_changed ) {
update_translations ( ) ;
emit_signal ( " localization_changed " ) ;
}
}
2020-07-11 00:52:52 +02:00
void LocalizationEditor : : update_translations ( ) {
if ( updating_translations ) {
return ;
}
updating_translations = true ;
translation_list - > clear ( ) ;
TreeItem * root = translation_list - > create_item ( nullptr ) ;
translation_list - > set_hide_root ( true ) ;
2021-02-17 17:44:49 +01:00
if ( ProjectSettings : : get_singleton ( ) - > has_setting ( " internationalization/locale/translations " ) ) {
2022-10-18 16:43:37 +02:00
PackedStringArray translations = GLOBAL_GET ( " internationalization/locale/translations " ) ;
2020-07-11 00:52:52 +02:00
for ( int i = 0 ; i < translations . size ( ) ; i + + ) {
TreeItem * t = translation_list - > create_item ( root ) ;
t - > set_editable ( 0 , false ) ;
t - > set_text ( 0 , translations [ i ] . replace_first ( " res:// " , " " ) ) ;
2022-08-29 15:55:49 +02:00
t - > set_tooltip_text ( 0 , translations [ i ] ) ;
2020-07-11 00:52:52 +02:00
t - > set_metadata ( 0 , i ) ;
2023-08-13 02:33:39 +02:00
t - > add_button ( 0 , get_editor_theme_icon ( SNAME ( " Remove " ) ) , 0 , false , TTR ( " Remove " ) ) ;
2020-07-11 00:52:52 +02:00
}
}
// Update translation remaps.
String remap_selected ;
if ( translation_remap - > get_selected ( ) ) {
remap_selected = translation_remap - > get_selected ( ) - > get_metadata ( 0 ) ;
}
translation_remap - > clear ( ) ;
translation_remap_options - > clear ( ) ;
root = translation_remap - > create_item ( nullptr ) ;
TreeItem * root2 = translation_remap_options - > create_item ( nullptr ) ;
translation_remap - > set_hide_root ( true ) ;
translation_remap_options - > set_hide_root ( true ) ;
translation_res_option_add_button - > set_disabled ( true ) ;
2021-02-17 17:44:49 +01:00
if ( ProjectSettings : : get_singleton ( ) - > has_setting ( " internationalization/locale/translation_remaps " ) ) {
2022-10-18 16:43:37 +02:00
Dictionary remaps = GLOBAL_GET ( " internationalization/locale/translation_remaps " ) ;
2020-07-11 00:52:52 +02:00
List < Variant > rk ;
remaps . get_key_list ( & rk ) ;
Vector < String > keys ;
2021-07-24 15:46:25 +02:00
for ( const Variant & E : rk ) {
2021-07-16 05:45:57 +02:00
keys . push_back ( E ) ;
2020-07-11 00:52:52 +02:00
}
keys . sort ( ) ;
for ( int i = 0 ; i < keys . size ( ) ; i + + ) {
TreeItem * t = translation_remap - > create_item ( root ) ;
t - > set_editable ( 0 , false ) ;
t - > set_text ( 0 , keys [ i ] . replace_first ( " res:// " , " " ) ) ;
2022-08-29 15:55:49 +02:00
t - > set_tooltip_text ( 0 , keys [ i ] ) ;
2020-07-11 00:52:52 +02:00
t - > set_metadata ( 0 , keys [ i ] ) ;
2023-08-13 02:33:39 +02:00
t - > add_button ( 0 , get_editor_theme_icon ( SNAME ( " Remove " ) ) , 0 , false , TTR ( " Remove " ) ) ;
2022-01-04 11:32:08 +01:00
// Display that it has been removed if this is the case.
if ( ! FileAccess : : exists ( keys [ i ] ) ) {
t - > set_text ( 0 , t - > get_text ( 0 ) + vformat ( " (%s) " , TTR ( " Removed " ) ) ) ;
2022-08-29 15:55:49 +02:00
t - > set_tooltip_text ( 0 , vformat ( TTR ( " %s cannot be found. " ) , t - > get_tooltip_text ( 0 ) ) ) ;
2022-01-04 11:32:08 +01:00
}
2020-07-11 00:52:52 +02:00
if ( keys [ i ] = = remap_selected ) {
t - > select ( 0 ) ;
translation_res_option_add_button - > set_disabled ( false ) ;
PackedStringArray selected = remaps [ keys [ i ] ] ;
for ( int j = 0 ; j < selected . size ( ) ; j + + ) {
2023-11-18 23:40:56 +01:00
const String & s2 = selected [ j ] ;
2020-07-11 00:52:52 +02:00
int qp = s2 . rfind ( " : " ) ;
String path = s2 . substr ( 0 , qp ) ;
String locale = s2 . substr ( qp + 1 , s2 . length ( ) ) ;
TreeItem * t2 = translation_remap_options - > create_item ( root2 ) ;
t2 - > set_editable ( 0 , false ) ;
t2 - > set_text ( 0 , path . replace_first ( " res:// " , " " ) ) ;
2022-08-29 15:55:49 +02:00
t2 - > set_tooltip_text ( 0 , path ) ;
2020-07-11 00:52:52 +02:00
t2 - > set_metadata ( 0 , j ) ;
2023-08-13 02:33:39 +02:00
t2 - > add_button ( 0 , get_editor_theme_icon ( SNAME ( " Remove " ) ) , 0 , false , TTR ( " Remove " ) ) ;
2021-09-23 13:08:50 +02:00
t2 - > set_cell_mode ( 1 , TreeItem : : CELL_MODE_CUSTOM ) ;
t2 - > set_text ( 1 , TranslationServer : : get_singleton ( ) - > get_locale_name ( locale ) ) ;
2020-07-11 00:52:52 +02:00
t2 - > set_editable ( 1 , true ) ;
t2 - > set_metadata ( 1 , path ) ;
2022-08-29 15:55:49 +02:00
t2 - > set_tooltip_text ( 1 , locale ) ;
2022-01-04 18:52:32 +01:00
// Display that it has been removed if this is the case.
if ( ! FileAccess : : exists ( path ) ) {
t2 - > set_text ( 0 , t2 - > get_text ( 0 ) + vformat ( " (%s) " , TTR ( " Removed " ) ) ) ;
2022-08-29 15:55:49 +02:00
t2 - > set_tooltip_text ( 0 , vformat ( TTR ( " %s cannot be found. " ) , t2 - > get_tooltip_text ( 0 ) ) ) ;
2022-01-04 18:52:32 +01:00
}
2020-07-11 00:52:52 +02:00
}
}
}
}
// Update translation POT files.
translation_pot_list - > clear ( ) ;
root = translation_pot_list - > create_item ( nullptr ) ;
translation_pot_list - > set_hide_root ( true ) ;
2023-03-02 07:38:59 +01:00
PackedStringArray pot_translations = GLOBAL_GET ( " internationalization/locale/translations_pot_files " ) ;
for ( int i = 0 ; i < pot_translations . size ( ) ; i + + ) {
TreeItem * t = translation_pot_list - > create_item ( root ) ;
t - > set_editable ( 0 , false ) ;
t - > set_text ( 0 , pot_translations [ i ] . replace_first ( " res:// " , " " ) ) ;
t - > set_tooltip_text ( 0 , pot_translations [ i ] ) ;
t - > set_metadata ( 0 , i ) ;
2023-08-13 02:33:39 +02:00
t - > add_button ( 0 , get_editor_theme_icon ( SNAME ( " Remove " ) ) , 0 , false , TTR ( " Remove " ) ) ;
2020-07-11 00:52:52 +02:00
}
// New translation parser plugin might extend possible file extensions in POT generation.
_update_pot_file_extensions ( ) ;
2023-03-02 07:38:59 +01:00
pot_generate_button - > set_disabled ( pot_translations . is_empty ( ) ) ;
2020-07-11 00:52:52 +02:00
updating_translations = false ;
}
void LocalizationEditor : : _bind_methods ( ) {
ClassDB : : bind_method ( D_METHOD ( " update_translations " ) , & LocalizationEditor : : update_translations ) ;
ADD_SIGNAL ( MethodInfo ( " localization_changed " ) ) ;
}
LocalizationEditor : : LocalizationEditor ( ) {
localization_changed = " localization_changed " ;
TabContainer * translations = memnew ( TabContainer ) ;
translations - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
add_child ( translations ) ;
{
VBoxContainer * tvb = memnew ( VBoxContainer ) ;
tvb - > set_name ( TTR ( " Translations " ) ) ;
translations - > add_child ( tvb ) ;
HBoxContainer * thb = memnew ( HBoxContainer ) ;
2021-07-08 15:29:15 +02:00
Label * l = memnew ( Label ( TTR ( " Translations: " ) ) ) ;
l - > set_theme_type_variation ( " HeaderSmall " ) ;
thb - > add_child ( l ) ;
2020-12-29 09:26:45 +01:00
thb - > add_spacer ( ) ;
2020-07-11 00:52:52 +02:00
tvb - > add_child ( thb ) ;
Button * addtr = memnew ( Button ( TTR ( " Add... " ) ) ) ;
addtr - > connect ( " pressed " , callable_mp ( this , & LocalizationEditor : : _translation_file_open ) ) ;
thb - > add_child ( addtr ) ;
VBoxContainer * tmc = memnew ( VBoxContainer ) ;
tmc - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
tvb - > add_child ( tmc ) ;
translation_list = memnew ( Tree ) ;
translation_list - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
tmc - > add_child ( translation_list ) ;
2021-09-23 13:08:50 +02:00
locale_select = memnew ( EditorLocaleDialog ) ;
locale_select - > connect ( " locale_selected " , callable_mp ( this , & LocalizationEditor : : _translation_res_option_selected ) ) ;
add_child ( locale_select ) ;
2020-07-11 00:52:52 +02:00
translation_file_open = memnew ( EditorFileDialog ) ;
2020-12-29 09:26:45 +01:00
translation_file_open - > set_file_mode ( EditorFileDialog : : FILE_MODE_OPEN_FILES ) ;
translation_file_open - > connect ( " files_selected " , callable_mp ( this , & LocalizationEditor : : _translation_add ) ) ;
2020-07-11 00:52:52 +02:00
add_child ( translation_file_open ) ;
}
{
VBoxContainer * tvb = memnew ( VBoxContainer ) ;
tvb - > set_name ( TTR ( " Remaps " ) ) ;
translations - > add_child ( tvb ) ;
HBoxContainer * thb = memnew ( HBoxContainer ) ;
2021-07-08 15:29:15 +02:00
Label * l = memnew ( Label ( TTR ( " Resources: " ) ) ) ;
l - > set_theme_type_variation ( " HeaderSmall " ) ;
thb - > add_child ( l ) ;
2020-07-11 00:52:52 +02:00
thb - > add_spacer ( ) ;
tvb - > add_child ( thb ) ;
Button * addtr = memnew ( Button ( TTR ( " Add... " ) ) ) ;
addtr - > connect ( " pressed " , callable_mp ( this , & LocalizationEditor : : _translation_res_file_open ) ) ;
thb - > add_child ( addtr ) ;
VBoxContainer * tmc = memnew ( VBoxContainer ) ;
tmc - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
tvb - > add_child ( tmc ) ;
translation_remap = memnew ( Tree ) ;
translation_remap - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
translation_remap - > connect ( " cell_selected " , callable_mp ( this , & LocalizationEditor : : _translation_res_select ) ) ;
2021-09-18 09:33:18 +02:00
translation_remap - > connect ( " button_clicked " , callable_mp ( this , & LocalizationEditor : : _translation_res_delete ) ) ;
2020-07-11 00:52:52 +02:00
tmc - > add_child ( translation_remap ) ;
translation_res_file_open_dialog = memnew ( EditorFileDialog ) ;
2020-12-29 09:26:45 +01:00
translation_res_file_open_dialog - > set_file_mode ( EditorFileDialog : : FILE_MODE_OPEN_FILES ) ;
translation_res_file_open_dialog - > connect ( " files_selected " , callable_mp ( this , & LocalizationEditor : : _translation_res_add ) ) ;
2020-07-11 00:52:52 +02:00
add_child ( translation_res_file_open_dialog ) ;
thb = memnew ( HBoxContainer ) ;
2021-07-08 15:29:15 +02:00
l = memnew ( Label ( TTR ( " Remaps by Locale: " ) ) ) ;
l - > set_theme_type_variation ( " HeaderSmall " ) ;
thb - > add_child ( l ) ;
2020-07-11 00:52:52 +02:00
thb - > add_spacer ( ) ;
tvb - > add_child ( thb ) ;
addtr = memnew ( Button ( TTR ( " Add... " ) ) ) ;
addtr - > connect ( " pressed " , callable_mp ( this , & LocalizationEditor : : _translation_res_option_file_open ) ) ;
translation_res_option_add_button = addtr ;
thb - > add_child ( addtr ) ;
tmc = memnew ( VBoxContainer ) ;
tmc - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
tvb - > add_child ( tmc ) ;
translation_remap_options = memnew ( Tree ) ;
translation_remap_options - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
translation_remap_options - > set_columns ( 2 ) ;
translation_remap_options - > set_column_title ( 0 , TTR ( " Path " ) ) ;
translation_remap_options - > set_column_title ( 1 , TTR ( " Locale " ) ) ;
translation_remap_options - > set_column_titles_visible ( true ) ;
translation_remap_options - > set_column_expand ( 0 , true ) ;
2021-07-04 05:13:28 +02:00
translation_remap_options - > set_column_clip_content ( 0 , true ) ;
2020-07-11 00:52:52 +02:00
translation_remap_options - > set_column_expand ( 1 , false ) ;
2021-09-23 13:08:50 +02:00
translation_remap_options - > set_column_clip_content ( 1 , false ) ;
translation_remap_options - > set_column_custom_minimum_width ( 1 , 250 ) ;
2020-07-11 00:52:52 +02:00
translation_remap_options - > connect ( " item_edited " , callable_mp ( this , & LocalizationEditor : : _translation_res_option_changed ) ) ;
2021-09-18 09:33:18 +02:00
translation_remap_options - > connect ( " button_clicked " , callable_mp ( this , & LocalizationEditor : : _translation_res_option_delete ) ) ;
2021-09-23 13:08:50 +02:00
translation_remap_options - > connect ( " custom_popup_edited " , callable_mp ( this , & LocalizationEditor : : _translation_res_option_popup ) ) ;
2020-07-11 00:52:52 +02:00
tmc - > add_child ( translation_remap_options ) ;
translation_res_option_file_open_dialog = memnew ( EditorFileDialog ) ;
2020-12-29 09:26:45 +01:00
translation_res_option_file_open_dialog - > set_file_mode ( EditorFileDialog : : FILE_MODE_OPEN_FILES ) ;
translation_res_option_file_open_dialog - > connect ( " files_selected " , callable_mp ( this , & LocalizationEditor : : _translation_res_option_add ) ) ;
2020-07-11 00:52:52 +02:00
add_child ( translation_res_option_file_open_dialog ) ;
}
{
VBoxContainer * tvb = memnew ( VBoxContainer ) ;
tvb - > set_name ( TTR ( " POT Generation " ) ) ;
translations - > add_child ( tvb ) ;
HBoxContainer * thb = memnew ( HBoxContainer ) ;
2021-07-08 15:29:15 +02:00
Label * l = memnew ( Label ( TTR ( " Files with translation strings: " ) ) ) ;
l - > set_theme_type_variation ( " HeaderSmall " ) ;
thb - > add_child ( l ) ;
2020-07-11 00:52:52 +02:00
thb - > add_spacer ( ) ;
tvb - > add_child ( thb ) ;
Button * addtr = memnew ( Button ( TTR ( " Add... " ) ) ) ;
addtr - > connect ( " pressed " , callable_mp ( this , & LocalizationEditor : : _pot_file_open ) ) ;
thb - > add_child ( addtr ) ;
2023-03-02 07:38:59 +01:00
pot_generate_button = memnew ( Button ( TTR ( " Generate POT " ) ) ) ;
pot_generate_button - > connect ( " pressed " , callable_mp ( this , & LocalizationEditor : : _pot_generate_open ) ) ;
thb - > add_child ( pot_generate_button ) ;
2020-07-11 00:52:52 +02:00
VBoxContainer * tmc = memnew ( VBoxContainer ) ;
tmc - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
tvb - > add_child ( tmc ) ;
translation_pot_list = memnew ( Tree ) ;
translation_pot_list - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
tmc - > add_child ( translation_pot_list ) ;
pot_generate_dialog = memnew ( EditorFileDialog ) ;
pot_generate_dialog - > set_file_mode ( EditorFileDialog : : FILE_MODE_SAVE_FILE ) ;
pot_generate_dialog - > connect ( " file_selected " , callable_mp ( this , & LocalizationEditor : : _pot_generate ) ) ;
add_child ( pot_generate_dialog ) ;
pot_file_open_dialog = memnew ( EditorFileDialog ) ;
2020-12-29 09:26:45 +01:00
pot_file_open_dialog - > set_file_mode ( EditorFileDialog : : FILE_MODE_OPEN_FILES ) ;
pot_file_open_dialog - > connect ( " files_selected " , callable_mp ( this , & LocalizationEditor : : _pot_add ) ) ;
2020-07-11 00:52:52 +02:00
add_child ( pot_file_open_dialog ) ;
}
}