Skip to content

Commit ab0e238

Browse files
authored
Add language selector (#2104)
For the English source and the single existing translation, Spanish. Use 2 buttons with the flat variation. Set them as not translatables, because the text in their own language must be displayed. Resolve #1729
1 parent 02c84a3 commit ab0e238

8 files changed

Lines changed: 106 additions & 2 deletions

File tree

locale/es.po

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
msgid ""
66
msgstr ""
77
"Project-Id-Version: Threadbare\n"
8-
"PO-Revision-Date: 2026-04-08 17:57-0300\n"
8+
"PO-Revision-Date: 2026-04-08 21:25-0300\n"
99
"Last-Translator: Manuel Quiñones <manuq@endlessaccess.org>\n"
1010
"Language-Team: Spanish\n"
1111
"Language: es\n"
@@ -60,6 +60,10 @@ msgstr "Ajustes de video"
6060
msgid "Fullscreen"
6161
msgstr "Pantalla completa"
6262

63+
#: scenes/menus/options/components/language_settings.tscn
64+
msgid "Language Settings"
65+
msgstr "Ajustes de idioma"
66+
6367
#: scenes/menus/debug/debug_settings.tscn
6468
msgid "Completed Quests"
6569
msgstr "Misiones completadas"

locale/threadbare.pot

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# res://scenes/menus/options/options.tscn
44
# res://scenes/menus/options/components/sound_settings.tscn
55
# res://scenes/menus/options/components/video_settings.tscn
6+
# res://scenes/menus/options/components/language_settings.tscn
67
# res://scenes/menus/debug/debug_settings.tscn
78
# res://scenes/globals/pause/pause_overlay.tscn
89
# res://scenes/menus/title/components/main_menu.gd
@@ -72,6 +73,10 @@ msgstr ""
7273
msgid "Fullscreen"
7374
msgstr ""
7475

76+
#: scenes/menus/options/components/language_settings.tscn
77+
msgid "Language Settings"
78+
msgstr ""
79+
7580
#: scenes/menus/debug/debug_settings.tscn
7681
msgid "Completed Quests"
7782
msgstr ""

project.godot

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ champ_walk_on_water={
283283
[internationalization]
284284

285285
locale/translations=PackedStringArray("res://locale/es.po")
286-
locale/translations_pot_files=PackedStringArray("res://scenes/menus/title/components/main_menu.tscn", "res://scenes/menus/options/options.tscn", "res://scenes/menus/options/components/sound_settings.tscn", "res://scenes/menus/options/components/video_settings.tscn", "res://scenes/menus/debug/debug_settings.tscn", "res://scenes/globals/pause/pause_overlay.tscn", "res://scenes/menus/title/components/main_menu.gd", "res://scenes/ui_elements/input_hints/aim_input_hint.tscn", "res://scenes/ui_elements/input_hints/interact_input_hint.tscn", "res://scenes/ui_elements/input_hints/movement_input_hint.tscn", "res://scenes/ui_elements/input_hints/repel_input_hint.tscn", "res://scenes/ui_elements/input_hints/reset_input_hint.tscn", "res://scenes/ui_elements/input_hints/run_input_hint.tscn", "res://scenes/ui_elements/input_hints/skip_input_hint.tscn", "res://scenes/ui_elements/input_hints/throw_input_hint.tscn", "res://scenes/ui_elements/input_hints/undo_input_hint.tscn")
286+
locale/translations_pot_files=PackedStringArray("res://scenes/menus/title/components/main_menu.tscn", "res://scenes/menus/options/options.tscn", "res://scenes/menus/options/components/sound_settings.tscn", "res://scenes/menus/options/components/video_settings.tscn", "res://scenes/menus/options/components/language_settings.tscn", "res://scenes/menus/debug/debug_settings.tscn", "res://scenes/globals/pause/pause_overlay.tscn", "res://scenes/menus/title/components/main_menu.gd", "res://scenes/ui_elements/input_hints/aim_input_hint.tscn", "res://scenes/ui_elements/input_hints/interact_input_hint.tscn", "res://scenes/ui_elements/input_hints/movement_input_hint.tscn", "res://scenes/ui_elements/input_hints/repel_input_hint.tscn", "res://scenes/ui_elements/input_hints/reset_input_hint.tscn", "res://scenes/ui_elements/input_hints/run_input_hint.tscn", "res://scenes/ui_elements/input_hints/skip_input_hint.tscn", "res://scenes/ui_elements/input_hints/throw_input_hint.tscn", "res://scenes/ui_elements/input_hints/undo_input_hint.tscn")
287287

288288
[layer_names]
289289

scenes/globals/settings/settings.gd

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ const DEFAULT_VOLUMES: Dictionary[String, float] = {
1515
"Music": 0.5,
1616
}
1717

18+
const LANGUAGE_SECTION := "Language"
19+
const LOCALE_KEY := "Locale"
20+
const DEFAULT_LOCALE := "en"
21+
1822
## 5:4 ratio of 1280×1024, 1024×768, and other pre-widescreen monitors.
1923
const MINIMUM_ASPECT_RATIO := 1.25
2024

@@ -38,6 +42,7 @@ func _ready() -> void:
3842
_settings.set_value(META_SECTION, VERSION_KEY, VERSION)
3943

4044
_restore_volumes()
45+
_restore_locale()
4146
_load_project_settings_overrides()
4247
_set_minimum_window_size()
4348

@@ -101,6 +106,16 @@ func toggle_fullscreen(toggled_on: bool) -> void:
101106
set_window_mode(DisplayServer.WINDOW_MODE_WINDOWED)
102107

103108

109+
func get_locale() -> String:
110+
return TranslationServer.get_locale()
111+
112+
113+
func set_locale(locale: String) -> void:
114+
TranslationServer.set_locale(locale)
115+
_settings.set_value(LANGUAGE_SECTION, LOCALE_KEY, locale)
116+
_save()
117+
118+
104119
func set_window_mode(window_mode: int) -> void:
105120
if window_mode == DisplayServer.window_get_mode():
106121
return
@@ -113,6 +128,11 @@ func set_window_mode(window_mode: int) -> void:
113128
push_warning("Failed to save to", _overrides_path, ": ", error_string(ret))
114129

115130

131+
func _restore_locale() -> void:
132+
var locale: String = _settings.get_value(LANGUAGE_SECTION, LOCALE_KEY, DEFAULT_LOCALE)
133+
TranslationServer.set_locale(locale)
134+
135+
116136
func _set_volume(bus_idx: int, volume_linear: float) -> void:
117137
AudioServer.set_bus_volume_linear(bus_idx, volume_linear)
118138

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# SPDX-FileCopyrightText: The Threadbare Authors
2+
# SPDX-License-Identifier: MPL-2.0
3+
extends HBoxContainer
4+
5+
@onready var _english_button: Button = %EnglishButton
6+
@onready var _spanish_button: Button = %SpanishButton
7+
8+
9+
func _ready() -> void:
10+
# There are two instances of this option in the game: one on the title screen, and
11+
# another in the pause overlay. At most one is displayed at a time, so we can keep them in
12+
# synch by reading the setting each time each option is displayed.
13+
visibility_changed.connect(_refresh)
14+
_refresh()
15+
16+
17+
func _refresh() -> void:
18+
var current_locale := Settings.get_locale()
19+
_english_button.set_pressed_no_signal(current_locale == "en")
20+
_spanish_button.set_pressed_no_signal(current_locale == "es")
21+
22+
23+
func _on_button_pressed(language_code: String) -> void:
24+
Settings.set_locale(language_code)
25+
_refresh()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
uid://dk2wa6nonu0jc
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
[gd_scene format=3 uid="uid://w0uscqwgsi4w"]
2+
3+
[ext_resource type="Theme" uid="uid://cvitou84ni7qe" path="res://scenes/ui_elements/components/theme.tres" id="1_abc"]
4+
[ext_resource type="Script" uid="uid://dk2wa6nonu0jc" path="res://scenes/menus/options/components/language_option.gd" id="2_abc"]
5+
6+
[node name="LanguageSettings" type="VBoxContainer" unique_id=85827291]
7+
offset_left = 96.0
8+
offset_top = 64.0
9+
offset_right = 544.0
10+
offset_bottom = 254.0
11+
theme = ExtResource("1_abc")
12+
13+
[node name="PanelContainer" type="PanelContainer" parent="." unique_id=1311807474]
14+
layout_mode = 2
15+
size_flags_horizontal = 0
16+
theme_type_variation = &"PlayerRibbon"
17+
18+
[node name="Label" type="Label" parent="PanelContainer" unique_id=1487597883]
19+
layout_mode = 2
20+
text = "Language Settings"
21+
22+
[node name="HBoxContainer" type="HBoxContainer" parent="." unique_id=1302951996]
23+
layout_mode = 2
24+
script = ExtResource("2_abc")
25+
26+
[node name="EnglishButton" type="Button" parent="HBoxContainer" unique_id=993974861]
27+
unique_name_in_owner = true
28+
auto_translate_mode = 2
29+
layout_mode = 2
30+
size_flags_horizontal = 3
31+
theme_type_variation = &"FlatButton"
32+
toggle_mode = true
33+
text = "English"
34+
35+
[node name="SpanishButton" type="Button" parent="HBoxContainer" unique_id=355814411]
36+
unique_name_in_owner = true
37+
auto_translate_mode = 2
38+
layout_mode = 2
39+
size_flags_horizontal = 3
40+
theme_type_variation = &"FlatButton"
41+
toggle_mode = true
42+
text = "Español"
43+
44+
[connection signal="pressed" from="HBoxContainer/EnglishButton" to="HBoxContainer" method="_on_button_pressed" binds= ["en"]]
45+
[connection signal="pressed" from="HBoxContainer/SpanishButton" to="HBoxContainer" method="_on_button_pressed" binds= ["es"]]

scenes/menus/options/options.tscn

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
[ext_resource type="Script" uid="uid://r7cjyiw5log4" path="res://scenes/menus/options/components/options.gd" id="2_cw13b"]
66
[ext_resource type="PackedScene" uid="uid://tahf2q1d3e74" path="res://scenes/menus/options/components/video_settings.tscn" id="4_cw13b"]
77
[ext_resource type="Texture2D" uid="uid://xe25gqovxxpe" path="res://assets/first_party/icons/left_arrow.png" id="5_qdq3g"]
8+
[ext_resource type="PackedScene" uid="uid://w0uscqwgsi4w" path="res://scenes/menus/options/components/language_settings.tscn" id="6_lang"]
89

910
[node name="Options" type="CenterContainer" unique_id=2066163370 node_paths=PackedStringArray("back_button")]
1011
anchors_preset = 15
@@ -30,6 +31,9 @@ layout_mode = 2
3031
[node name="VideoSettings" parent="PanelContainer/VBoxContainer" unique_id=201104966 instance=ExtResource("4_cw13b")]
3132
layout_mode = 2
3233

34+
[node name="LanguageSettings" parent="PanelContainer/VBoxContainer" unique_id=1730937504 instance=ExtResource("6_lang")]
35+
layout_mode = 2
36+
3337
[node name="BackButton" type="Button" parent="PanelContainer/VBoxContainer" unique_id=200110196]
3438
unique_name_in_owner = true
3539
layout_mode = 2

0 commit comments

Comments
 (0)