Use typed GDScript

This commit is contained in:
Marc Gilleron 2020-06-14 19:20:03 +01:00
parent 588011258e
commit bcad9cd60e
9 changed files with 280 additions and 275 deletions

View File

@ -1,25 +1,26 @@
tool tool
static func load_csv_translation(filepath): # TODO Can't type nullable return value
var f = File.new() static func load_csv_translation(filepath: String):
var err = f.open(filepath, File.READ) var f := File.new()
var err := f.open(filepath, File.READ)
if err != OK: if err != OK:
printerr("Could not open ", filepath, " for read, code ", err) printerr("Could not open ", filepath, " for read, code ", err)
return null return null
var first_row = f.get_csv_line() var first_row := f.get_csv_line()
if first_row[0] != "id": if first_row[0] != "id":
printerr("Translation file is missing the `id` column") printerr("Translation file is missing the `id` column")
return null return null
var languages = PoolStringArray() var languages := PoolStringArray()
for i in range(1, len(first_row)): for i in range(1, len(first_row)):
languages.append(first_row[i]) languages.append(first_row[i])
var ids = [] var ids := []
var rows = [] var rows := []
while not f.eof_reached(): while not f.eof_reached():
var row = f.get_csv_line() var row := f.get_csv_line()
if len(row) < 1 or row[0].strip_edges() == "": if len(row) < 1 or row[0].strip_edges() == "":
printerr("Found an empty row") printerr("Found an empty row")
continue continue
@ -33,9 +34,9 @@ static func load_csv_translation(filepath):
rows.append(trans) rows.append(trans)
f.close() f.close()
var translations = {} var translations := {}
for i in len(ids): for i in len(ids):
var t = {} var t := {}
for language_index in len(rows[i]): for language_index in len(rows[i]):
t[languages[language_index]] = rows[i][language_index] t[languages[language_index]] = rows[i][language_index]
translations[ids[i]] = { "translations": t, "comments": "" } translations[ids[i]] = { "translations": t, "comments": "" }
@ -44,37 +45,37 @@ static func load_csv_translation(filepath):
class _Sorter: class _Sorter:
func sort(a, b): func sort(a: Array, b: Array):
return a[0] < b[0] return a[0] < b[0]
static func save_csv_translation(filepath, data): static func save_csv_translation(filepath: String, data: Dictionary) -> Array:
print("Saving: ", data) print("Saving: ", data)
var languages = {} var languages_set := {}
for id in data: for id in data:
var s = data[id] var s = data[id]
for language in s.translations: for language in s.translations:
languages[language] = true languages_set[language] = true
if len(languages) == 0: if len(languages_set) == 0:
printerr("No language found, nothing to save") printerr("No language found, nothing to save")
return [] return []
languages = languages.keys() var languages := languages_set.keys()
languages.sort() languages.sort()
var first_row = ["id"] var first_row := ["id"]
first_row.resize(len(languages) + 1) first_row.resize(len(languages) + 1)
for i in len(languages): for i in len(languages):
first_row[i + 1] = languages[i] first_row[i + 1] = languages[i]
var rows = [] var rows := []
rows.resize(len(data)) rows.resize(len(data))
var row_index = 0 var row_index := 0
for id in data: for id in data:
var s = data[id] var s : Dictionary = data[id]
var row = [] var row := []
row.resize(len(languages) + 1) row.resize(len(languages) + 1)
row[0] = id row[0] = id
for i in len(languages): for i in len(languages):
@ -84,14 +85,14 @@ static func save_csv_translation(filepath, data):
row[i + 1] = text row[i + 1] = text
rows[row_index] = row rows[row_index] = row
row_index += 1 row_index += 1
print(rows)
var sorter = _Sorter.new() var sorter := _Sorter.new()
rows.sort_custom(sorter, "sort") rows.sort_custom(sorter, "sort")
var delim = "," var delim := ","
var f = File.new() var f := File.new()
var err = f.open(filepath, File.WRITE) var err := f.open(filepath, File.WRITE)
if err != OK: if err != OK:
printerr("Could not open ", filepath, " for write, code ", err) printerr("Could not open ", filepath, " for write, code ", err)
return [] return []
@ -102,15 +103,15 @@ static func save_csv_translation(filepath, data):
f.close() f.close()
print("Saved ", filepath) print("Saved ", filepath)
var saved_languages = languages var saved_languages := languages
return saved_languages return saved_languages
static func store_csv_line(f, a, delim = ","): static func store_csv_line(f: File, a: Array, delim := ","):
for i in len(a): for i in len(a):
if i > 0: if i > 0:
f.store_string(",") f.store_string(",")
var text = str(a[i]) var text := str(a[i])
# Behavior taken from LibreOffice # Behavior taken from LibreOffice
if text.find(delim) != -1 or text.find('"') != -1 or text.find("\n") != -1: if text.find(delim) != -1 or text.find('"') != -1 or text.find("\n") != -1:
text = str('"', text.replace('"', '""'), '"') text = str('"', text.replace('"', '""'), '"')

View File

@ -8,26 +8,26 @@ signal progress_reported(ratio)
# TODO Do we want to know if a text is found multiple times in the same file? # TODO Do we want to know if a text is found multiple times in the same file?
# text => { file => line number } # text => { file => line number }
var _strings = {} var _strings := {}
var _thread = null var _thread : Thread = null
var _time_before = 0.0 var _time_before := 0.0
var _ignored_paths = {} var _ignored_paths := {}
var _paths = [] var _paths := []
func extract_async(root, ignored_paths=[]): func extract_async(root: String, ignored_paths := []):
_prepare(root, ignored_paths) _prepare(root, ignored_paths)
_thread = Thread.new() _thread = Thread.new()
_thread.start(self, "_extract_thread_func", root) _thread.start(self, "_extract_thread_func", root)
func extract(root, ignored_paths=[]): func extract(root: String, ignored_paths := []) -> Dictionary:
_prepare(root, ignored_paths) _prepare(root, ignored_paths)
_extract(root) _extract(root)
return _strings return _strings
func _prepare(root, ignored_paths): func _prepare(root: String, ignored_paths: Array):
_time_before = OS.get_ticks_msec() _time_before = OS.get_ticks_msec()
assert(_thread == null) assert(_thread == null)
@ -38,17 +38,17 @@ func _prepare(root, ignored_paths):
_strings.clear() _strings.clear()
func _extract(root): func _extract(root: String):
_walk(root, funcref(self, "_index_file"), funcref(self, "_filter")) _walk(root, funcref(self, "_index_file"), funcref(self, "_filter"))
for i in len(_paths): for i in len(_paths):
var fpath = _paths[i] var fpath : String = _paths[i]
var f = File.new() var f := File.new()
var err = f.open(fpath, File.READ) var err := f.open(fpath, File.READ)
if err != OK: if err != OK:
printerr("Could not open '", fpath, "', for read, error ", err) printerr("Could not open '", fpath, "', for read, error ", err)
continue continue
var ext = fpath.get_extension() var ext := fpath.get_extension()
match ext: match ext:
"tscn": "tscn":
_process_tscn(f, fpath) _process_tscn(f, fpath)
@ -58,24 +58,24 @@ func _extract(root):
call_deferred("_report_progress", float(i) / float(len(_paths))) call_deferred("_report_progress", float(i) / float(len(_paths)))
func _extract_thread_func(root): func _extract_thread_func(root: String):
_extract(root) _extract(root)
call_deferred("_finished") call_deferred("_finished")
func _report_progress(ratio): func _report_progress(ratio: float):
emit_signal("progress_reported", ratio) emit_signal("progress_reported", ratio)
func _finished(): func _finished():
_thread.wait_to_finish() _thread.wait_to_finish()
_thread = null _thread = null
var elapsed = float(OS.get_ticks_msec() - _time_before) / 1000.0 var elapsed := float(OS.get_ticks_msec() - _time_before) / 1000.0
print("Extraction took ", elapsed, " seconds") print("Extraction took ", elapsed, " seconds")
emit_signal("finished", _strings) emit_signal("finished", _strings)
func _filter(path): func _filter(path: String) -> bool:
if path in _ignored_paths: if path in _ignored_paths:
return false return false
if path[0] == ".": if path[0] == ".":
@ -83,41 +83,40 @@ func _filter(path):
return true return true
func _index_file(fpath): func _index_file(fpath: String):
var ext = fpath.get_extension() var ext := fpath.get_extension()
#print("File ", fpath) #print("File ", fpath)
if ext != "tscn" and ext != "gd": if ext != "tscn" and ext != "gd":
return return
_paths.append(fpath) _paths.append(fpath)
func _process_tscn(f, fpath): func _process_tscn(f: File, fpath: String):
# TOOD Also search for "window_title" and "dialog_text" # TOOD Also search for "window_title" and "dialog_text"
var pattern = "text =" var pattern := "text ="
var text = "" var text := ""
var state = STATE_SEARCHING var state := STATE_SEARCHING
var line_number = 0 var line_number := 0
while not f.eof_reached(): while not f.eof_reached():
var line = f.get_line() var line := f.get_line()
line_number += 1 line_number += 1
if line == "": if line == "":
continue continue
match state: match state:
STATE_SEARCHING: STATE_SEARCHING:
var i = line.find(pattern) var i := line.find(pattern)
if i != -1: if i != -1:
var begin_quote_index = line.find('"', i + len(pattern)) var begin_quote_index := line.find('"', i + len(pattern))
if begin_quote_index == -1: if begin_quote_index == -1:
printerr("Could not find begin quote after text property, in ", printerr("Could not find begin quote after text property, in ",
fpath, " line ", line_number) fpath, " line ", line_number)
continue continue
var end_quote_index = line.rfind('"') var end_quote_index := line.rfind('"')
if end_quote_index != -1 and end_quote_index > begin_quote_index \ if end_quote_index != -1 and end_quote_index > begin_quote_index \
and line[end_quote_index - 1] != '\\': and line[end_quote_index - 1] != '\\':
@ -144,23 +143,23 @@ func _process_tscn(f, fpath):
text = str(text, line, "\n") text = str(text, line, "\n")
func _process_gd(f, fpath): func _process_gd(f: File, fpath: String):
var text = "" var text := ""
var line_number = 0 var line_number := 0
while not f.eof_reached(): while not f.eof_reached():
var line = f.get_line().strip_edges() var line := f.get_line().strip_edges()
line_number += 1 line_number += 1
if line == "" or line[0] == "#": if line == "" or line[0] == "#":
continue continue
# Search for one or multiple tr("...") in the same line # Search for one or multiple tr("...") in the same line
var search_index = 0 var search_index := 0
var counter = 0 var counter := 0
while true: while true:
var pattern = "tr(" var pattern := "tr("
var call_index = line.find(pattern, search_index) var call_index := line.find(pattern, search_index)
if call_index == -1: if call_index == -1:
pattern = "TranslationServer.translate(" pattern = "TranslationServer.translate("
call_index = line.find(pattern, search_index) call_index = line.find(pattern, search_index)
@ -177,18 +176,18 @@ func _process_gd(f, fpath):
# TODO There may be more cases to handle # TODO There may be more cases to handle
# They may need regexes or a simplified GDScript parser to extract properly # They may need regexes or a simplified GDScript parser to extract properly
var begin_quote_index = line.find('"', call_index) var begin_quote_index := line.find('"', call_index)
if begin_quote_index == -1: if begin_quote_index == -1:
# Multiline or procedural strings not supported # Multiline or procedural strings not supported
printerr("Begin quote not found in ", fpath, " line ", line_number) printerr("Begin quote not found in ", fpath, " line ", line_number)
break break
var end_quote_index = find_unescaped_quote(line, begin_quote_index + 1) var end_quote_index := find_unescaped_quote(line, begin_quote_index + 1)
if end_quote_index == -1: if end_quote_index == -1:
# Multiline or procedural strings not supported # Multiline or procedural strings not supported
printerr("End quote not found in ", fpath, " line ", line_number) printerr("End quote not found in ", fpath, " line ", line_number)
break break
text = line.substr(begin_quote_index + 1, end_quote_index - begin_quote_index - 1) text = line.substr(begin_quote_index + 1, end_quote_index - begin_quote_index - 1)
var end_bracket_index = line.find(')', end_quote_index) var end_bracket_index := line.find(')', end_quote_index)
if end_bracket_index == -1: if end_bracket_index == -1:
# Multiline or procedural strings not supported # Multiline or procedural strings not supported
printerr("End bracket not found in ", fpath, " line ", line_number) printerr("End bracket not found in ", fpath, " line ", line_number)
@ -201,7 +200,7 @@ func _process_gd(f, fpath):
assert(counter < 100) assert(counter < 100)
static func find_unescaped_quote(s, from): static func find_unescaped_quote(s, from) -> int:
while true: while true:
var i = s.find('"', from) var i = s.find('"', from)
if i <= 0: if i <= 0:
@ -209,25 +208,26 @@ static func find_unescaped_quote(s, from):
if s[i - 1] != '\\': if s[i - 1] != '\\':
return i return i
from = i + 1 from = i + 1
return -1
func _add_string(file, line_number, text): func _add_string(file: String, line_number: int, text: String):
if not _strings.has(text): if not _strings.has(text):
_strings[text] = {} _strings[text] = {}
_strings[text][file] = line_number _strings[text][file] = line_number
static func _walk(folder_path, file_action, filter): static func _walk(folder_path: String, file_action: FuncRef, filter: FuncRef):
#print("Walking dir ", folder_path) #print("Walking dir ", folder_path)
var d = Directory.new() var d := Directory.new()
var err = d.open(folder_path) var err := d.open(folder_path)
if err != OK: if err != OK:
printerr("Could not open directory '", folder_path, "', error ", err) printerr("Could not open directory '", folder_path, "', error ", err)
return return
d.list_dir_begin(true, true) d.list_dir_begin(true, true)
var fname = d.get_next() var fname := d.get_next()
while fname != "": while fname != "":
var fullpath = folder_path.plus_file(fname) var fullpath := folder_path.plus_file(fname)
if filter == null or filter.call_func(fullpath) == true: if filter == null or filter.call_func(fullpath) == true:
if d.current_is_dir(): if d.current_is_dir():
_walk(fullpath, file_action, filter) _walk(fullpath, file_action, filter)

View File

@ -5,30 +5,29 @@ const Extractor = preload("./extractor.gd")
signal import_selected(strings) signal import_selected(strings)
onready var _root_path_edit = $VBoxContainer/HBoxContainer/RootPathEdit onready var _root_path_edit : LineEdit = $VBoxContainer/HBoxContainer/RootPathEdit
onready var _excluded_dirs_edit = $VBoxContainer/Options/ExcludedDirsEdit onready var _excluded_dirs_edit : LineEdit = $VBoxContainer/Options/ExcludedDirsEdit
onready var _summary_label = $VBoxContainer/StatusBar/SummaryLabel onready var _summary_label : Label = $VBoxContainer/StatusBar/SummaryLabel
onready var _results_list = $VBoxContainer/Results onready var _results_list : Tree = $VBoxContainer/Results
onready var _progress_bar = $VBoxContainer/StatusBar/ProgressBar onready var _progress_bar : ProgressBar = $VBoxContainer/StatusBar/ProgressBar
onready var _extract_button = $VBoxContainer/Buttons/ExtractButton onready var _extract_button : Button = $VBoxContainer/Buttons/ExtractButton
onready var _import_button = $VBoxContainer/Buttons/ImportButton onready var _import_button : Button = $VBoxContainer/Buttons/ImportButton
var _extractor = null var _extractor : Extractor = null
# { string => { fpath => line number } } # { string => { fpath => line number } }
var _results = {} var _results := {}
var _registered_string_filter = null var _registered_string_filter : FuncRef = null
func _ready(): func _ready():
_import_button.disabled = true _import_button.disabled = true
func set_registered_string_filter(registered_string_filter): func set_registered_string_filter(registered_string_filter: FuncRef):
assert(registered_string_filter is FuncRef)
_registered_string_filter = registered_string_filter _registered_string_filter = registered_string_filter
func _notification(what): func _notification(what: int):
if what == NOTIFICATION_VISIBILITY_CHANGED: if what == NOTIFICATION_VISIBILITY_CHANGED:
if visible: if visible:
_summary_label.text = "" _summary_label.text = ""
@ -44,13 +43,13 @@ func _on_ExtractButton_pressed():
if _extractor != null: if _extractor != null:
return return
var root = _root_path_edit.text.strip_edges() var root := _root_path_edit.text.strip_edges()
var d = Directory.new() var d := Directory.new()
if not d.dir_exists(root): if not d.dir_exists(root):
printerr("Directory `", root, "` does not exist") printerr("Directory `", root, "` does not exist")
return return
var excluded_dirs = _excluded_dirs_edit.text.split(";", false) var excluded_dirs := _excluded_dirs_edit.text.split(";", false)
for i in len(excluded_dirs): for i in len(excluded_dirs):
excluded_dirs[i] = excluded_dirs[i].strip_edges() excluded_dirs[i] = excluded_dirs[i].strip_edges()
@ -82,20 +81,20 @@ func _on_Extractor_progress_reported(ratio):
_progress_bar.value = 100.0 * ratio _progress_bar.value = 100.0 * ratio
func _on_Extractor_finished(results): func _on_Extractor_finished(results: Dictionary):
print("Extractor finished") print("Extractor finished")
_progress_bar.value = 100 _progress_bar.value = 100
_progress_bar.hide() _progress_bar.hide()
_results_list.clear() _results_list.clear()
var registered_set = {} var registered_set := {}
var new_set = {} var new_set := {}
# TODO We might actually want to not filter, in order to update location comments # TODO We might actually want to not filter, in order to update location comments
# Filter results # Filter results
if _registered_string_filter != null: if _registered_string_filter != null:
var texts = results.keys() var texts := results.keys()
for text in texts: for text in texts:
if _registered_string_filter.call_func(text): if _registered_string_filter.call_func(text):
results.erase(text) results.erase(text)
@ -105,16 +104,16 @@ func _on_Extractor_finished(results):
_results_list.create_item() _results_list.create_item()
for text in results: for text in results:
var item = _results_list.create_item() var item : TreeItem = _results_list.create_item()
item.set_text(0, text) item.set_text(0, text)
item.collapsed = true item.collapsed = true
new_set[text] = true new_set[text] = true
var files = results[text] var files = results[text]
for file in files: for file in files:
var line_number = files[file] var line_number : int = files[file]
var file_item = _results_list.create_item(item) var file_item : TreeItem = _results_list.create_item(item)
file_item.set_text(0, str(file, ": ", line_number)) file_item.set_text(0, str(file, ": ", line_number))
_results = results _results = results

View File

@ -5,11 +5,11 @@ const Locales = preload("./locales.gd")
signal language_selected(language) signal language_selected(language)
onready var _filter_edit = $VBoxContainer/FilterEdit onready var _filter_edit : LineEdit = $VBoxContainer/FilterEdit
onready var _languages_list = $VBoxContainer/LanguagesList onready var _languages_list : Tree = $VBoxContainer/LanguagesList
onready var _ok_button = $VBoxContainer/Buttons/OkButton onready var _ok_button : Button = $VBoxContainer/Buttons/OkButton
var _hidden_locales = [] var _hidden_locales := []
func configure(hidden_locales): func configure(hidden_locales):
@ -20,8 +20,8 @@ func configure(hidden_locales):
func refresh_list(): func refresh_list():
_languages_list.clear() _languages_list.clear()
var filter = _filter_edit.text.strip_edges() var filter := _filter_edit.text.strip_edges()
var locales = Locales.get_all_locales() var locales := Locales.get_all_locales()
# Hidden root # Hidden root
_languages_list.create_item() _languages_list.create_item()
@ -31,7 +31,7 @@ func refresh_list():
continue continue
if filter != "" and locale[0].findn(filter) == -1: if filter != "" and locale[0].findn(filter) == -1:
continue continue
var item = _languages_list.create_item() var item : TreeItem = _languages_list.create_item()
item.set_text(0, locale[0]) item.set_text(0, locale[0])
item.set_text(1, locale[1]) item.set_text(1, locale[1])
@ -39,7 +39,7 @@ func refresh_list():
func submit(): func submit():
var item = _languages_list.get_selected() var item := _languages_list.get_selected()
emit_signal("language_selected", item.get_text(0)) emit_signal("language_selected", item.get_text(0))
hide() hide()

View File

@ -363,12 +363,12 @@ const _locales = [
] ]
static func get_all_locales(): static func get_all_locales() -> Array:
return _locales return _locales
static func get_all_locale_ids(): static func get_all_locale_ids() -> Array:
var ids = [] var ids := []
ids.resize(len(_locales)) ids.resize(len(_locales))
for i in len(_locales): for i in len(_locales):
ids[i] = _locales[i][0] ids[i] = _locales[i][0]

View File

@ -1,18 +1,19 @@
tool tool
extends EditorPlugin extends EditorPlugin
var TranslationEditor = load("res://addons/zylann.translation_editor/tools/translation_editor.tscn") const TranslationEditor = preload("./translation_editor.gd")
const TranslationEditorScene = preload("./translation_editor.tscn")
var _main_control = null var _main_control : TranslationEditor = null
func _enter_tree(): func _enter_tree():
print("Translation editor plugin Enter tree") print("Translation editor plugin Enter tree")
var editor_interface = get_editor_interface() var editor_interface := get_editor_interface()
var base_control = editor_interface.get_base_control() var base_control := editor_interface.get_base_control()
_main_control = TranslationEditor.instance() _main_control = TranslationEditorScene.instance()
_main_control.configure_for_godot_integration(base_control) _main_control.configure_for_godot_integration(base_control)
_main_control.hide() _main_control.hide()
editor_interface.get_editor_viewport().add_child(_main_control) editor_interface.get_editor_viewport().add_child(_main_control)
@ -25,19 +26,19 @@ func _exit_tree():
_main_control = null _main_control = null
func has_main_screen(): func has_main_screen() -> bool:
return true return true
func get_plugin_name(): func get_plugin_name() -> String:
return "Localization" return "Localization"
func get_plugin_icon(): func get_plugin_icon() -> Texture:
return preload("icons/icon_translation_editor.svg") return preload("icons/icon_translation_editor.svg")
func make_visible(visible): func make_visible(visible: bool):
_main_control.visible = visible _main_control.visible = visible

View File

@ -4,51 +4,52 @@ const STATE_NONE = 0
const STATE_MSGID = 1 const STATE_MSGID = 1
const STATE_MSGSTR = 2 const STATE_MSGSTR = 2
static func load_po_translation(folder_path, valid_locales): # TODO Can't type nullable result
var all_strings = {} static func load_po_translation(folder_path: String, valid_locales: Array):
var config = {} var all_strings := {}
var config := {}
# TODO Get languages from configs, not from filenames # TODO Get languages from configs, not from filenames
var languages = get_languages_in_folder(folder_path, valid_locales) var languages := get_languages_in_folder(folder_path, valid_locales)
if len(languages) == 0: if len(languages) == 0:
printerr("No .po languages were found in ", folder_path) printerr("No .po languages were found in ", folder_path)
return all_strings return all_strings
for language in languages: for language in languages:
var filepath = folder_path.plus_file(str(language, ".po")) var filepath := folder_path.plus_file(str(language, ".po"))
var f = File.new() var f := File.new()
var err = f.open(filepath, File.READ) var err := f.open(filepath, File.READ)
if err != OK: if err != OK:
printerr("Could not open file ", filepath, " for read, error ", err) printerr("Could not open file ", filepath, " for read, error ", err)
return null return null
f.store_line("") f.store_line("")
var state = STATE_NONE var state := STATE_NONE
var comment = "" var comment := ""
var msgid = "" var msgid := ""
var msgstr = "" var msgstr := ""
var ids = [] var ids := []
var translations = [] var translations := []
var comments = [] var comments := []
# For debugging # For debugging
var line_number = -1 var line_number := -1
while not f.eof_reached(): while not f.eof_reached():
var line = f.get_line().strip_edges() var line := f.get_line().strip_edges()
line_number += 1 line_number += 1
if line != "" and line[0] == "#": if line != "" and line[0] == "#":
var comment_line = line.right(1).strip_edges() var comment_line := line.right(1).strip_edges()
if comment == "": if comment == "":
comment = str(comment, comment_line) comment = str(comment, comment_line)
else: else:
comment = str(comment, "\n", comment_line) comment = str(comment, "\n", comment_line)
continue continue
var space_index = line.find(" ") var space_index := line.find(" ")
if line.begins_with("msgid"): if line.begins_with("msgid"):
msgid = _parse_msg(line.right(space_index)) msgid = _parse_msg(line.right(space_index))
@ -66,7 +67,7 @@ static func load_po_translation(folder_path, valid_locales):
msgstr = str(msgstr, _parse_msg(line)) msgstr = str(msgstr, _parse_msg(line))
elif line == "" and state == STATE_MSGSTR: elif line == "" and state == STATE_MSGSTR:
var s = null var s : Dictionary
if msgid == "": if msgid == "":
assert(len(msgstr) != 0) assert(len(msgstr) != 0)
config = _parse_config(msgstr) config = _parse_config(msgstr)
@ -96,7 +97,7 @@ static func load_po_translation(folder_path, valid_locales):
return all_strings return all_strings
static func _parse_msg(s): static func _parse_msg(s: String) -> String:
s = s.strip_edges() s = s.strip_edges()
assert(s[0] == '"') assert(s[0] == '"')
var end = s.rfind('"') var end = s.rfind('"')
@ -104,9 +105,9 @@ static func _parse_msg(s):
return msg.c_unescape().replace('\\"', '"') return msg.c_unescape().replace('\\"', '"')
static func _parse_config(text): static func _parse_config(text: String) -> Dictionary:
var config = {} var config := {}
var lines = text.split("\n", false) var lines := text.split("\n", false)
print("Config lines: ", lines) print("Config lines: ", lines)
for line in lines: for line in lines:
var splits = line.split(":") var splits = line.split(":")
@ -116,25 +117,26 @@ static func _parse_config(text):
class _Sorter: class _Sorter:
func sort(a, b): func sort(a: Array, b: Array):
return a[0] < b[0] return a[0] < b[0]
static func save_po_translations(folder_path, translations, languages_to_save): static func save_po_translations(folder_path: String, translations: Dictionary,
var sorter = _Sorter.new() languages_to_save: Array) -> Array:
var saved_languages = []
var sorter := _Sorter.new()
var saved_languages := []
for language in languages_to_save: for language in languages_to_save:
var f := File.new()
var f = File.new() var filepath := folder_path.plus_file(str(language, ".po"))
var filepath = folder_path.plus_file(str(language, ".po")) var err := f.open(filepath, File.WRITE)
var err = f.open(filepath, File.WRITE)
if err != OK: if err != OK:
printerr("Could not open file ", filepath, " for write, error ", err) printerr("Could not open file ", filepath, " for write, error ", err)
continue continue
# TODO Take as argument # TODO Take as argument
var config = { var config := {
"Project-Id-Version": ProjectSettings.get_setting("application/config/name"), "Project-Id-Version": ProjectSettings.get_setting("application/config/name"),
"MIME-Version": "1.0", "MIME-Version": "1.0",
"Content-Type": "text/plain; charset=UTF-8", "Content-Type": "text/plain; charset=UTF-8",
@ -143,17 +145,17 @@ static func save_po_translations(folder_path, translations, languages_to_save):
} }
# Write config # Write config
var config_msg = "" var config_msg := ""
for k in config: for k in config:
config_msg = str(config_msg, k, ": ", config[k], "\n") config_msg = str(config_msg, k, ": ", config[k], "\n")
_write_msg(f, "msgid", "") _write_msg(f, "msgid", "")
_write_msg(f, "msgstr", config_msg) _write_msg(f, "msgstr", config_msg)
f.store_line("") f.store_line("")
var items = [] var items := []
for id in translations: for id in translations:
var s = translations[id] var s : Dictionary = translations[id]
if not s.translations.has(language): if not s.translations.has(language):
continue continue
items.append([id, s.translations[language], s.comments]) items.append([id, s.translations[language], s.comments])
@ -161,8 +163,7 @@ static func save_po_translations(folder_path, translations, languages_to_save):
items.sort_custom(sorter, "sort") items.sort_custom(sorter, "sort")
for item in items: for item in items:
var comment : String = item[2]
var comment = item[2]
if comment != "": if comment != "":
var comment_lines = comment.split("\n") var comment_lines = comment.split("\n")
for line in comment_lines: for line in comment_lines:
@ -179,8 +180,8 @@ static func save_po_translations(folder_path, translations, languages_to_save):
return saved_languages return saved_languages
static func _write_msg(f, msgtype, msg): static func _write_msg(f: File, msgtype: String, msg: String):
var lines = msg.split("\n") var lines := msg.split("\n")
# `split` removes the newlines, so we'll add them back. # `split` removes the newlines, so we'll add them back.
# Empty lines may happen if the original text has multiple successsive line breaks. # Empty lines may happen if the original text has multiple successsive line breaks.
# However, if the text ends with a newline, it will produce an empty string at the end, # However, if the text ends with a newline, it will produce an empty string at the end,
@ -216,20 +217,20 @@ static func _write_msg(f, msgtype, msg):
f.store_line(str(" \"", lines[i], "\"")) f.store_line(str(" \"", lines[i], "\""))
static func get_languages_in_folder(folder_path, valid_locales): static func get_languages_in_folder(folder_path: String, valid_locales: Array) -> Array:
var result = [] var result := []
var d = Directory.new() var d := Directory.new()
var err = d.open(folder_path) var err := d.open(folder_path)
if err != OK: if err != OK:
printerr("Could not open directory ", folder_path, ", error ", err) printerr("Could not open directory ", folder_path, ", error ", err)
return result return result
d.list_dir_begin() d.list_dir_begin()
var fname = d.get_next() var fname := d.get_next()
while fname != "": while fname != "":
if not d.current_is_dir(): if not d.current_is_dir():
var ext = fname.get_extension() var ext := fname.get_extension()
if ext == "po": if ext == "po":
var language = fname.get_basename().get_file() var language := fname.get_basename().get_file()
if valid_locales.find(language) != -1: if valid_locales.find(language) != -1:
result.append(language) result.append(language)
fname = d.get_next() fname = d.get_next()

View File

@ -3,29 +3,27 @@ extends WindowDialog
signal submitted(str_id, prev_str_id) signal submitted(str_id, prev_str_id)
onready var _line_edit = $VBoxContainer/LineEdit onready var _line_edit : LineEdit = $VBoxContainer/LineEdit
onready var _ok_button = $VBoxContainer/Buttons/OkButton onready var _ok_button : Button = $VBoxContainer/Buttons/OkButton
onready var _hint_label = $VBoxContainer/HintLabel onready var _hint_label : Label = $VBoxContainer/HintLabel
var _validator_func = null var _validator_func : FuncRef = null
var _prev_str_id = null var _prev_str_id := ""
func set_replaced_str_id(str_id): func set_replaced_str_id(str_id: String):
assert(typeof(str_id) == TYPE_STRING or str_id == null)
_prev_str_id = str_id _prev_str_id = str_id
if typeof(str_id) == TYPE_STRING: _line_edit.text = str_id
_line_edit.text = str_id
func set_validator(f): func set_validator(f: FuncRef):
_validator_func = f _validator_func = f
func _notification(what): func _notification(what: int):
if what == NOTIFICATION_VISIBILITY_CHANGED: if what == NOTIFICATION_VISIBILITY_CHANGED:
if visible: if visible:
if _prev_str_id == null: if _prev_str_id == "":
window_title = "New string ID" window_title = "New string ID"
else: else:
window_title = str("Replace `", _prev_str_id, "`") window_title = str("Replace `", _prev_str_id, "`")
@ -33,14 +31,14 @@ func _notification(what):
_validate() _validate()
func _on_LineEdit_text_changed(new_text): func _on_LineEdit_text_changed(new_text: String):
_validate() _validate()
func _validate(): func _validate():
var new_text = _line_edit.text.strip_edges() var new_text := _line_edit.text.strip_edges()
var valid = not new_text.empty() var valid := not new_text.empty()
var hint_message = "" var hint_message := ""
if _validator_func != null: if _validator_func != null:
var res = _validator_func.call_func(new_text) var res = _validator_func.call_func(new_text)
@ -54,7 +52,7 @@ func _validate():
# Note: hiding the label would shift up other controls in the container # Note: hiding the label would shift up other controls in the container
func _on_LineEdit_text_entered(new_text): func _on_LineEdit_text_entered(new_text: String):
submit() submit()
@ -67,7 +65,7 @@ func _on_CancelButton_pressed():
func submit(): func submit():
var s = _line_edit.text.strip_edges() var s := _line_edit.text.strip_edges()
emit_signal("submitted", s, _prev_str_id) emit_signal("submitted", s, _prev_str_id)
hide() hide()

View File

@ -4,9 +4,13 @@ extends Panel
const CsvLoader = preload("./csv_loader.gd") const CsvLoader = preload("./csv_loader.gd")
const PoLoader = preload("./po_loader.gd") const PoLoader = preload("./po_loader.gd")
const Locales = preload("./locales.gd") const Locales = preload("./locales.gd")
const StringEditionDialog = preload("./string_edition_dialog.tscn") const StringEditionDialog = preload("./string_edition_dialog.gd")
const LanguageSelectionDialog = preload("./language_selection_dialog.tscn") const LanguageSelectionDialog = preload("./language_selection_dialog.gd")
const ExtractorDialog = preload("./extractor_dialog.tscn") const ExtractorDialog = preload("./extractor_dialog.gd")
const StringEditionDialogScene = preload("./string_edition_dialog.tscn")
const LanguageSelectionDialogScene = preload("./language_selection_dialog.tscn")
const ExtractorDialogScene = preload("./extractor_dialog.tscn")
const MENU_FILE_OPEN = 0 const MENU_FILE_OPEN = 0
const MENU_FILE_SAVE = 1 const MENU_FILE_SAVE = 1
@ -19,34 +23,35 @@ const MENU_FILE_EXTRACT = 6
const FORMAT_CSV = 0 const FORMAT_CSV = 0
const FORMAT_GETTEXT = 1 const FORMAT_GETTEXT = 1
onready var _file_menu = $VBoxContainer/MenuBar/FileMenu onready var _file_menu : MenuButton = $VBoxContainer/MenuBar/FileMenu
onready var _edit_menu = $VBoxContainer/MenuBar/EditMenu onready var _edit_menu : MenuButton = $VBoxContainer/MenuBar/EditMenu
onready var _search_edit = $VBoxContainer/Main/LeftPane/Search/Search onready var _search_edit : LineEdit = $VBoxContainer/Main/LeftPane/Search/Search
onready var _clear_search_button = $VBoxContainer/Main/LeftPane/Search/ClearSearch onready var _clear_search_button : Button = $VBoxContainer/Main/LeftPane/Search/ClearSearch
onready var _string_list = $VBoxContainer/Main/LeftPane/StringList onready var _string_list : ItemList = $VBoxContainer/Main/LeftPane/StringList
onready var _translation_tab_container = \ onready var _translation_tab_container : TabContainer = \
$VBoxContainer/Main/RightPane/VSplitContainer/TranslationTabContainer $VBoxContainer/Main/RightPane/VSplitContainer/TranslationTabContainer
onready var _notes_edit = $VBoxContainer/Main/RightPane/VSplitContainer/VBoxContainer/NotesEdit onready var _notes_edit : TextEdit = \
onready var _status_label = $VBoxContainer/StatusBar/Label $VBoxContainer/Main/RightPane/VSplitContainer/VBoxContainer/NotesEdit
onready var _status_label : Label = $VBoxContainer/StatusBar/Label
var _string_edit_dialog = null var _string_edit_dialog : StringEditionDialog = null
var _language_selection_dialog = null var _language_selection_dialog : LanguageSelectionDialog = null
var _remove_language_confirmation_dialog = null var _remove_language_confirmation_dialog : ConfirmationDialog = null
var _remove_string_confirmation_dialog = null var _remove_string_confirmation_dialog : ConfirmationDialog = null
var _extractor_dialog = null var _extractor_dialog : ExtractorDialog = null
var _open_dialog = null var _open_dialog : FileDialog = null
var _save_file_dialog = null var _save_file_dialog : FileDialog = null
var _save_folder_dialog = null var _save_folder_dialog : FileDialog = null
# This is set when integrated as a Godot plugin # This is set when integrated as a Godot plugin
var _base_control = null var _base_control : Control = null
var _translation_edits = {} var _translation_edits := {}
var _dialogs_to_free_on_exit = [] var _dialogs_to_free_on_exit := []
var _data = {} var _data := {}
var _languages = [] var _languages := []
var _current_path = null var _current_path := ""
var _current_format = FORMAT_CSV var _current_format := FORMAT_CSV
var _modified_languages = {} var _modified_languages := {}
func _ready(): func _ready():
@ -100,12 +105,12 @@ func _setup_dialogs():
_save_folder_dialog.connect("dir_selected", self, "_on_SaveFolderDialog_dir_selected") _save_folder_dialog.connect("dir_selected", self, "_on_SaveFolderDialog_dir_selected")
_add_dialog(_save_folder_dialog) _add_dialog(_save_folder_dialog)
_string_edit_dialog = StringEditionDialog.instance() _string_edit_dialog = StringEditionDialogScene.instance()
_string_edit_dialog.set_validator(funcref(self, "_validate_new_string_id")) _string_edit_dialog.set_validator(funcref(self, "_validate_new_string_id"))
_string_edit_dialog.connect("submitted", self, "_on_StringEditionDialog_submitted") _string_edit_dialog.connect("submitted", self, "_on_StringEditionDialog_submitted")
_add_dialog(_string_edit_dialog) _add_dialog(_string_edit_dialog)
_language_selection_dialog = LanguageSelectionDialog.instance() _language_selection_dialog = LanguageSelectionDialogScene.instance()
_language_selection_dialog.connect( _language_selection_dialog.connect(
"language_selected", self, "_on_LanguageSelectionDialog_language_selected") "language_selected", self, "_on_LanguageSelectionDialog_language_selected")
_add_dialog(_language_selection_dialog) _add_dialog(_language_selection_dialog)
@ -117,7 +122,7 @@ func _setup_dialogs():
"confirmed", self, "_on_RemoveLanguageConfirmationDialog_confirmed") "confirmed", self, "_on_RemoveLanguageConfirmationDialog_confirmed")
_add_dialog(_remove_language_confirmation_dialog) _add_dialog(_remove_language_confirmation_dialog)
_extractor_dialog = ExtractorDialog.instance() _extractor_dialog = ExtractorDialogScene.instance()
_extractor_dialog.set_registered_string_filter(funcref(self, "_is_string_registered")) _extractor_dialog.set_registered_string_filter(funcref(self, "_is_string_registered"))
_extractor_dialog.connect("import_selected", self, "_on_ExtractorDialog_import_selected") _extractor_dialog.connect("import_selected", self, "_on_ExtractorDialog_import_selected")
_add_dialog(_extractor_dialog) _add_dialog(_extractor_dialog)
@ -130,7 +135,7 @@ func _setup_dialogs():
_add_dialog(_remove_string_confirmation_dialog) _add_dialog(_remove_string_confirmation_dialog)
func _add_dialog(dialog): func _add_dialog(dialog: Control):
if _base_control != null: if _base_control != null:
_base_control.add_child(dialog) _base_control.add_child(dialog)
_dialogs_to_free_on_exit.append(dialog) _dialogs_to_free_on_exit.append(dialog)
@ -146,7 +151,7 @@ func _exit_tree():
_dialogs_to_free_on_exit.clear() _dialogs_to_free_on_exit.clear()
func configure_for_godot_integration(base_control): func configure_for_godot_integration(base_control: Control):
# You have to call this before adding to the tree # You have to call this before adding to the tree
assert(not is_inside_tree()) assert(not is_inside_tree())
_base_control = base_control _base_control = base_control
@ -155,7 +160,7 @@ func configure_for_godot_integration(base_control):
self_modulate = Color(0, 0, 0, 0) self_modulate = Color(0, 0, 0, 0)
func _on_FileMenu_id_pressed(id): func _on_FileMenu_id_pressed(id: int):
match id: match id:
MENU_FILE_OPEN: MENU_FILE_OPEN:
_open() _open()
@ -174,7 +179,7 @@ func _on_FileMenu_id_pressed(id):
_language_selection_dialog.popup_centered_ratio() _language_selection_dialog.popup_centered_ratio()
MENU_FILE_REMOVE_LANGUAGE: MENU_FILE_REMOVE_LANGUAGE:
var language = get_current_language() var language := get_current_language()
_remove_language_confirmation_dialog.window_title = \ _remove_language_confirmation_dialog.window_title = \
str("Remove language `", language, "`") str("Remove language `", language, "`")
_remove_language_confirmation_dialog.popup_centered_minsize() _remove_language_confirmation_dialog.popup_centered_minsize()
@ -183,19 +188,19 @@ func _on_FileMenu_id_pressed(id):
_extractor_dialog.popup_centered_minsize() _extractor_dialog.popup_centered_minsize()
func _on_EditMenu_id_pressed(id): func _on_EditMenu_id_pressed(id: int):
pass pass
func _on_OpenDialog_file_selected(filepath): func _on_OpenDialog_file_selected(filepath: String):
load_file(filepath) load_file(filepath)
func _on_SaveFileDialog_file_selected(filepath): func _on_SaveFileDialog_file_selected(filepath: String):
save_file(filepath, FORMAT_CSV) save_file(filepath, FORMAT_CSV)
func _on_SaveFolderDialog_dir_selected(filepath): func _on_SaveFolderDialog_dir_selected(filepath: String):
save_file(filepath, FORMAT_GETTEXT) save_file(filepath, FORMAT_GETTEXT)
@ -207,7 +212,7 @@ func _on_SaveButton_pressed():
_save() _save()
func _on_LanguageSelectionDialog_language_selected(language): func _on_LanguageSelectionDialog_language_selected(language: String):
_add_language(language) _add_language(language)
@ -216,18 +221,18 @@ func _open():
func _save(): func _save():
if _current_path == null: if _current_path == "":
# Have to default to CSV for now... # Have to default to CSV for now...
_save_file_dialog.popup_centered_ratio() _save_file_dialog.popup_centered_ratio()
else: else:
save_file(_current_path, _current_format) save_file(_current_path, _current_format)
func load_file(filepath): func load_file(filepath: String):
var ext = filepath.get_extension() var ext := filepath.get_extension()
if ext == "po": if ext == "po":
var valid_locales = Locales.get_all_locale_ids() var valid_locales := Locales.get_all_locale_ids()
_current_path = filepath.get_base_dir() _current_path = filepath.get_base_dir()
_data = PoLoader.load_po_translation(_current_path, valid_locales) _data = PoLoader.load_po_translation(_current_path, valid_locales)
_current_format = FORMAT_GETTEXT _current_format = FORMAT_GETTEXT
@ -243,7 +248,7 @@ func load_file(filepath):
_languages.clear() _languages.clear()
for strid in _data: for strid in _data:
var s = _data[strid] var s : Dictionary = _data[strid]
for language in s.translations: for language in s.translations:
if _languages.find(language) == -1: if _languages.find(language) == -1:
_languages.append(language) _languages.append(language)
@ -264,7 +269,7 @@ func load_file(filepath):
func _update_status_label(): func _update_status_label():
if _current_path == null: if _current_path == "":
_status_label.text = "No file loaded" _status_label.text = "No file loaded"
elif _current_format == FORMAT_CSV: elif _current_format == FORMAT_CSV:
_status_label.text = _current_path _status_label.text = _current_path
@ -272,27 +277,27 @@ func _update_status_label():
_status_label.text = str(_current_path, " (Gettext translations folder)") _status_label.text = str(_current_path, " (Gettext translations folder)")
func _create_translation_edit(language): func _create_translation_edit(language: String):
assert(not _translation_edits.has(language)) # boom assert(not _translation_edits.has(language)) # boom
var edit = TextEdit.new() var edit := TextEdit.new()
edit.hide() edit.hide()
var tab_index = _translation_tab_container.get_tab_count() var tab_index := _translation_tab_container.get_tab_count()
_translation_tab_container.add_child(edit) _translation_tab_container.add_child(edit)
_translation_tab_container.set_tab_title(tab_index, language) _translation_tab_container.set_tab_title(tab_index, language)
_translation_edits[language] = edit _translation_edits[language] = edit
edit.connect("text_changed", self, "_on_TranslationEdit_text_changed", [language]) edit.connect("text_changed", self, "_on_TranslationEdit_text_changed", [language])
func _on_TranslationEdit_text_changed(language): func _on_TranslationEdit_text_changed(language: String):
var edit = _translation_edits[language] var edit : TextEdit = _translation_edits[language]
var selected_strids = _string_list.get_selected_items() var selected_strids := _string_list.get_selected_items()
# TODO Don't show the editor if no strings are selected # TODO Don't show the editor if no strings are selected
if len(selected_strids) != 1: if len(selected_strids) != 1:
return return
#assert(len(selected_strids) == 1) #assert(len(selected_strids) == 1)
var strid = _string_list.get_item_text(selected_strids[0]) var strid := _string_list.get_item_text(selected_strids[0])
var prev_text = null var prev_text : String
var s = _data[strid] var s : Dictionary = _data[strid]
if s.translations.has(language): if s.translations.has(language):
prev_text = s.translations[language] prev_text = s.translations[language]
if prev_text != edit.text: if prev_text != edit.text:
@ -301,34 +306,34 @@ func _on_TranslationEdit_text_changed(language):
func _on_NotesEdit_text_changed(): func _on_NotesEdit_text_changed():
var selected_strids = _string_list.get_selected_items() var selected_strids := _string_list.get_selected_items()
# TODO Don't show the editor if no strings are selected # TODO Don't show the editor if no strings are selected
if len(selected_strids) != 1: if len(selected_strids) != 1:
return return
#assert(len(selected_strids) == 1) #assert(len(selected_strids) == 1)
var strid = _string_list.get_item_text(selected_strids[0]) var strid := _string_list.get_item_text(selected_strids[0])
var s = _data[strid] var s : Dictionary = _data[strid]
if s.comments != _notes_edit.text: if s.comments != _notes_edit.text:
s.comments = _notes_edit.text s.comments = _notes_edit.text
for language in _languages: for language in _languages:
_set_language_modified(language) _set_language_modified(language)
func _set_language_modified(language): func _set_language_modified(language: String):
if _modified_languages.has(language): if _modified_languages.has(language):
return return
_modified_languages[language] = true _modified_languages[language] = true
_set_language_tab_title(language, str(language, "*")) _set_language_tab_title(language, str(language, "*"))
func _set_language_unmodified(language): func _set_language_unmodified(language: String):
if not _modified_languages.has(language): if not _modified_languages.has(language):
return return
_modified_languages.erase(language) _modified_languages.erase(language)
_set_language_tab_title(language, language) _set_language_tab_title(language, language)
func _set_language_tab_title(language, title): func _set_language_tab_title(language: String, title: String):
var page = _translation_edits[language] var page = _translation_edits[language]
for i in _translation_tab_container.get_child_count(): for i in _translation_tab_container.get_child_count():
if _translation_tab_container.get_child(i) == page: if _translation_tab_container.get_child(i) == page:
@ -341,21 +346,21 @@ func _set_language_tab_title(language, title):
assert(false) assert(false)
func get_current_language(): func get_current_language() -> String:
var page = _translation_tab_container.get_current_tab_control() var page = _translation_tab_container.get_current_tab_control()
for language in _translation_edits: for language in _translation_edits:
if _translation_edits[language] == page: if _translation_edits[language] == page:
return language return language
# Something bad happened # Something bad happened
assert(false) assert(false)
return null return ""
func save_file(path, format): func save_file(path: String, format: int):
var saved_languages = [] var saved_languages := []
if format == FORMAT_GETTEXT: if format == FORMAT_GETTEXT:
var languages_to_save var languages_to_save : Array
if _current_format != FORMAT_GETTEXT: if _current_format != FORMAT_GETTEXT:
languages_to_save = _languages languages_to_save = _languages
else: else:
@ -377,9 +382,9 @@ func save_file(path, format):
func refresh_list(): func refresh_list():
var search_text = _search_edit.text.strip_edges() var search_text := _search_edit.text.strip_edges()
var sorted_strids = [] var sorted_strids := []
if search_text == "": if search_text == "":
sorted_strids = _data.keys() sorted_strids = _data.keys()
else: else:
@ -394,11 +399,11 @@ func refresh_list():
_string_list.add_item(strid) _string_list.add_item(strid)
func _on_StringList_item_selected(index): func _on_StringList_item_selected(index: int):
var str_id = _string_list.get_item_text(index) var str_id := _string_list.get_item_text(index)
var s = _data[str_id] var s : Dictionary = _data[str_id]
for language in _languages: for language in _languages:
var e = _translation_edits[language] var e : TextEdit = _translation_edits[language]
#e.show() #e.show()
if s.translations.has(language): if s.translations.has(language):
e.text = s.translations[language] e.text = s.translations[language]
@ -408,7 +413,7 @@ func _on_StringList_item_selected(index):
func _on_AddButton_pressed(): func _on_AddButton_pressed():
_string_edit_dialog.set_replaced_str_id(null) _string_edit_dialog.set_replaced_str_id("")
_string_edit_dialog.popup_centered() _string_edit_dialog.popup_centered()
@ -416,17 +421,17 @@ func _on_RemoveButton_pressed():
var selected_items = _string_list.get_selected_items() var selected_items = _string_list.get_selected_items()
if len(selected_items) == 0: if len(selected_items) == 0:
return return
var str_id = _string_list.get_item_text(selected_items[0]) var str_id := _string_list.get_item_text(selected_items[0])
_remove_string_confirmation_dialog.window_title = str("Remove `", str_id, "`") _remove_string_confirmation_dialog.window_title = str("Remove `", str_id, "`")
_remove_string_confirmation_dialog.popup_centered_minsize() _remove_string_confirmation_dialog.popup_centered_minsize()
func _on_RemoveStringConfirmationDialog_confirmed(): func _on_RemoveStringConfirmationDialog_confirmed():
var selected_items = _string_list.get_selected_items() var selected_items := _string_list.get_selected_items()
if len(selected_items) == 0: if len(selected_items) == 0:
printerr("No selected string??") printerr("No selected string??")
return return
var strid = _string_list.get_item_text(selected_items[0]) var strid := _string_list.get_item_text(selected_items[0])
_string_list.remove_item(selected_items[0]) _string_list.remove_item(selected_items[0])
_data.erase(strid) _data.erase(strid)
for language in _languages: for language in _languages:
@ -434,22 +439,22 @@ func _on_RemoveStringConfirmationDialog_confirmed():
func _on_RenameButton_pressed(): func _on_RenameButton_pressed():
var selected_items = _string_list.get_selected_items() var selected_items := _string_list.get_selected_items()
if len(selected_items) == 0: if len(selected_items) == 0:
return return
var str_id = _string_list.get_item_text(selected_items[0]) var str_id := _string_list.get_item_text(selected_items[0])
_string_edit_dialog.set_replaced_str_id(str_id) _string_edit_dialog.set_replaced_str_id(str_id)
_string_edit_dialog.popup_centered() _string_edit_dialog.popup_centered()
func _on_StringEditionDialog_submitted(str_id, prev_str_id): func _on_StringEditionDialog_submitted(str_id: String, prev_str_id: String):
if prev_str_id == null: if prev_str_id == "":
add_new_string(str_id) add_new_string(str_id)
else: else:
rename_string(prev_str_id, str_id) rename_string(prev_str_id, str_id)
func _validate_new_string_id(str_id): func _validate_new_string_id(str_id: String):
if _data.has(str_id): if _data.has(str_id):
return "Already existing" return "Already existing"
if str_id.strip_edges() != str_id: if str_id.strip_edges() != str_id:
@ -460,10 +465,10 @@ func _validate_new_string_id(str_id):
return true return true
func add_new_string(strid): func add_new_string(strid: String):
print("Adding new string ", strid) print("Adding new string ", strid)
assert(not _data.has(strid)) assert(not _data.has(strid))
var s = { var s := {
"translations": {}, "translations": {},
"comments": "" "comments": ""
} }
@ -473,9 +478,9 @@ func add_new_string(strid):
_set_language_modified(language) _set_language_modified(language)
func rename_string(old_strid, new_strid): func rename_string(old_strid: String, new_strid: String):
assert(_data.has(old_strid)) assert(_data.has(old_strid))
var s = _data[old_strid] var s : Dictionary = _data[old_strid]
_data.erase(old_strid) _data.erase(old_strid)
_data[new_strid] = s _data[new_strid] = s
for i in _string_list.get_item_count(): for i in _string_list.get_item_count():
@ -484,24 +489,24 @@ func rename_string(old_strid, new_strid):
break break
func _add_language(language): func _add_language(language: String):
assert(_languages.find(language) == -1) assert(_languages.find(language) == -1)
_create_translation_edit(language) _create_translation_edit(language)
_languages.append(language) _languages.append(language)
_set_language_modified(language) _set_language_modified(language)
var menu_index = _file_menu.get_popup().get_item_index(MENU_FILE_REMOVE_LANGUAGE) var menu_index := _file_menu.get_popup().get_item_index(MENU_FILE_REMOVE_LANGUAGE)
_file_menu.get_popup().set_item_disabled(menu_index, false) _file_menu.get_popup().set_item_disabled(menu_index, false)
print("Added language ", language) print("Added language ", language)
func _remove_language(language): func _remove_language(language: String):
assert(_languages.find(language) != -1) assert(_languages.find(language) != -1)
_set_language_unmodified(language) _set_language_unmodified(language)
var edit = _translation_edits[language] var edit : TextEdit = _translation_edits[language]
edit.queue_free() edit.queue_free()
_translation_edits.erase(language) _translation_edits.erase(language)
_languages.erase(language) _languages.erase(language)
@ -514,25 +519,25 @@ func _remove_language(language):
func _on_RemoveLanguageConfirmationDialog_confirmed(): func _on_RemoveLanguageConfirmationDialog_confirmed():
var language = get_current_language() var language := get_current_language()
_remove_language(language) _remove_language(language)
# Used as callback for filtering # Used as callback for filtering
func _is_string_registered(text): func _is_string_registered(text: String) -> bool:
if _data == null: if _data == null:
print("No data") print("No data")
return false return false
return _data.has(text) return _data.has(text)
func _on_ExtractorDialog_import_selected(results): func _on_ExtractorDialog_import_selected(results: Dictionary):
for text in results: for text in results:
if not _is_string_registered(text): if not _is_string_registered(text):
add_new_string(text) add_new_string(text)
func _on_Search_text_changed(search_text): func _on_Search_text_changed(search_text: String):
_clear_search_button.visible = (search_text != "") _clear_search_button.visible = (search_text != "")
refresh_list() refresh_list()