Localization (#15)

## Changes (escoria-core)
> Pending to do a PR to the core.
- Added `es` langcode with the corresponding flag image.
- Translated literals for `es`

## Changes (gymkhana)
-  Added `turno_cocina` localization csv.
- Proof of concept for tooltips & dialogs.

## Notes
- For tooltips just use the literals. Godot will automatically search for a translation key first.
- For ESC just use `translation_key:"Default text"`

## How to test
- In the option menu ES should be selectable.
- The `frontal` item in the inventory should have the tooltips and the `say` command translated in `en`,`fr` and `es`.

Reviewed-on: gymkhana/gymkhana#15
Co-authored-by: oier <oierbravo@gmail.com>
Co-committed-by: oier <oierbravo@gmail.com>
This commit is contained in:
2023-09-26 00:13:55 +02:00
committed by Oier Bravo
parent 6cbd466f76
commit 2d32f4b312
22 changed files with 241 additions and 72 deletions

View File

@@ -0,0 +1,118 @@
# `say_random player list_id lenght [offset]`
#
# Displays the specified string as dialog spoken by the player. This command
# blocks further event execution until the dialog has finished being 'said'
# (either as displayed text or as audible speech from a file).
#
# Global variables can be substituted into the text by wrapping the global
# name in braces.
# e.g. say player "I have {coin_count} coins remaining".
#
# **Parameters**
#
# - *player*: Global ID of the `ESCPlayer` or `ESCItem` object that is active.
# You can specify `current_player` in order to refer to the currently active
# player, e.g. in cases where multiple players are playable such as in games
# like Maniac Mansion or Day of the Tentacle.
# - *randomizer_list_id*: ID for the list of sentences.
# - *lenght*: lenght of the list.
# - *offset*: starting offset index of the list.
#
# Example: `say_random player random_list 4`
#
# @ESC
extends ESCBaseCommand
class_name SayRandomCommand
const CURRENT_PLAYER_KEYWORD = "CURRENT_PLAYER"
var rng: RandomNumberGenerator
# Constructor
func _init() -> void:
rng = RandomNumberGenerator.new()
# Return the descriptor of the arguments of this command
func configure() -> ESCCommandArgumentDescriptor:
return ESCCommandArgumentDescriptor.new(
3,
[TYPE_STRING, TYPE_STRING, TYPE_INT, TYPE_INT],
[
null,
null,
null,
0
],
[
true,
false,
false,
false
]
)
# Validate whether the given arguments match the command descriptor
func validate(arguments: Array):
if not .validate(arguments):
return false
if arguments[0].to_upper() != CURRENT_PLAYER_KEYWORD \
and not escoria.object_manager.has(arguments[0]):
escoria.logger.error(
self,
"[%s]: Invalid object: Object with global id %s not found."
% [get_command_name(), arguments[0]]
)
return false
return true
# Run the command
func run(command_params: Array) -> int:
escoria.current_state = escoria.GAME_STATE.DIALOG
if !escoria.dialog_player:
escoria.logger.error(
self,
"[%s]: No dialog player was registered and the say command was encountered."
% get_command_name()
)
escoria.current_state = escoria.GAME_STATE.DEFAULT
return ESCExecution.RC_ERROR
if not escoria.main.current_scene.player:
escoria.logger.warn(
self,
"[%s]: No player item in the current scene was registered and the say command was encountered."
% get_command_name()
)
escoria.current_state = escoria.GAME_STATE.DEFAULT
return ESCExecution.RC_CANCEL
var text = command_params[1] + "_" + String(rng.randi_range(command_params[2],command_params[3])) + ':" "'
var speaking_character_global_id = escoria.main.current_scene.player.global_id \
if command_params[0].to_upper() == CURRENT_PLAYER_KEYWORD \
else command_params[0]
escoria.dialog_player.say(
speaking_character_global_id,
"",
text
)
yield(escoria.dialog_player, "say_finished")
escoria.current_state = escoria.GAME_STATE.DEFAULT
return ESCExecution.RC_OK
# Function called when the command is interrupted.
func interrupt():
escoria.logger.debug(
self,
"[%s] interrupt() function not implemented." % get_command_name()
)

View File

@@ -46,7 +46,7 @@ onready var is_paused: bool = true
# Enable bbcode and catch the signal when a tween completed
func _ready():
_text_time_per_character = ProjectSettings.get_setting(
SimpleDialogPlugin.TEXT_TIME_PER_LETTER_MS
RTMISimpleDialogPlugin.TEXT_TIME_PER_LETTER_MS
)
if _text_time_per_character < 0:
@@ -54,15 +54,15 @@ func _ready():
self,
"%s setting must be a non-negative number. Will use default value of %s." %
[
SimpleDialogPlugin.TEXT_TIME_PER_LETTER_MS,
SimpleDialogPlugin.TEXT_TIME_PER_LETTER_MS_DEFAULT_VALUE
RTMISimpleDialogPlugin.TEXT_TIME_PER_LETTER_MS,
RTMISimpleDialogPlugin.TEXT_TIME_PER_LETTER_MS_DEFAULT_VALUE
]
)
_text_time_per_character = SimpleDialogPlugin.TEXT_TIME_PER_LETTER_MS_DEFAULT_VALUE
_text_time_per_character = RTMISimpleDialogPlugin.TEXT_TIME_PER_LETTER_MS_DEFAULT_VALUE
_fast_text_time_per_character = ProjectSettings.get_setting(
SimpleDialogPlugin.TEXT_TIME_PER_LETTER_MS_FAST
RTMISimpleDialogPlugin.TEXT_TIME_PER_LETTER_MS_FAST
)
if _fast_text_time_per_character < 0:
@@ -70,15 +70,15 @@ func _ready():
self,
"%s setting must be a non-negative number. Will use default value of %s." %
[
SimpleDialogPlugin.TEXT_TIME_PER_LETTER_MS_FAST,
SimpleDialogPlugin.TEXT_TIME_PER_LETTER_MS_FAST_DEFAULT_VALUE
RTMISimpleDialogPlugin.TEXT_TIME_PER_LETTER_MS_FAST,
RTMISimpleDialogPlugin.TEXT_TIME_PER_LETTER_MS_FAST_DEFAULT_VALUE
]
)
_fast_text_time_per_character = SimpleDialogPlugin.TEXT_TIME_PER_LETTER_MS_FAST_DEFAULT_VALUE
_fast_text_time_per_character = RTMISimpleDialogPlugin.TEXT_TIME_PER_LETTER_MS_FAST_DEFAULT_VALUE
_reading_speed_in_wpm = ProjectSettings.get_setting(
SimpleDialogPlugin.READING_SPEED_IN_WPM
RTMISimpleDialogPlugin.READING_SPEED_IN_WPM
)
if _reading_speed_in_wpm <= 0:
@@ -86,12 +86,12 @@ func _ready():
self,
"%s setting must be a positive number. Will use default value of %s." %
[
SimpleDialogPlugin.READING_SPEED_IN_WPM,
SimpleDialogPlugin.READING_SPEED_IN_WPM_DEFAULT_VALUE
RTMISimpleDialogPlugin.READING_SPEED_IN_WPM,
RTMISimpleDialogPlugin.READING_SPEED_IN_WPM_DEFAULT_VALUE
]
)
_reading_speed_in_wpm = SimpleDialogPlugin.READING_SPEED_IN_WPM_DEFAULT_VALUE
_reading_speed_in_wpm = RTMISimpleDialogPlugin.READING_SPEED_IN_WPM_DEFAULT_VALUE
_word_regex.compile("\\S+")
@@ -227,7 +227,7 @@ func _get_number_of_words() -> int:
# Ending the dialog
func _on_dialog_finished():
# Only trigger to clear the text if we aren't limiting the clearing trigger to a click.
if not ESCProjectSettingsManager.get_setting(SimpleDialogPlugin.CLEAR_TEXT_BY_CLICK_ONLY):
if not ESCProjectSettingsManager.get_setting(RTMISimpleDialogPlugin.CLEAR_TEXT_BY_CLICK_ONLY):
emit_signal("say_finished")

View File

@@ -18,3 +18,4 @@ func set_outline_color(color):
func set_outline_width(new_width):
Width = new_width
update()

View File

@@ -1,2 +1,3 @@
:action3
say player "Es mi frontal de toda la vida, le tengo cariño"
say player frontal_action3_say:"Es mi frontal de toda la vida, le tengo cariño"

View File

@@ -15,7 +15,7 @@ esc_script = "res://gymkhana/items/inventory/turno_cocina_frontal.esc"
inventory_texture = ExtResource( 2 )
dialog_color = Color( 1, 1, 1, 1 )
tooltips = {
"action3": "Admirar",
"action3": "frontal_action3",
"action4": "Usar"
}
combine_when_selected_action_is_in = [ "action4" ]

View File

@@ -45,7 +45,7 @@ is_exit = true
combine_when_selected_action_is_in = [ ]
dialog_color = Color( 1, 1, 1, 1 )
tooltips = {
"action1": "Entrar en la cocina"
"action1": "cocina_delante_puerta_cocina_action1"
}
animations = null
@@ -68,7 +68,7 @@ is_exit = true
combine_when_selected_action_is_in = [ ]
dialog_color = Color( 1, 1, 1, 1 )
tooltips = {
"action1": "Bajar a la despensa"
"action1": "cocina_delante_puerta_despensa_action1"
}
animations = null
@@ -91,7 +91,7 @@ is_exit = true
combine_when_selected_action_is_in = [ ]
dialog_color = Color( 1, 1, 1, 1 )
tooltips = {
"action1": "Ir detrás"
"action1": "cocina_delante_puerta_detras_action1"
}
animations = null
@@ -109,12 +109,12 @@ global_id = "puerta_detras_start"
position = Vector2( 813, 440 )
dialog_color = Color( 0, 1, 0.462745, 1 )
tooltips = {
"action1": "Observar sujeto",
"action2": "Hablar"
"action1": "cocina_delante_eneko_smoking_action1",
"action2": "cocina_delante_eneko_smoking_action2"
}
action3_target_texts = {
"bombona2": "Toma, un regalo",
"caja_herramientas": "Regalar"
"caja_herramientas": "Regalar",
"turno_cocina_frontal": "Ofrecer"
}
target_when_selected_action_is_in = [ "action3" ]
selectable = true
@@ -134,3 +134,25 @@ position = Vector2( 1425, 527 )
script = ExtResource( 5 )
global_id = "new_game_start_location"
is_start_location = true
[node name="pegatinas" type="Area2D" parent="."]
pause_mode = 1
position = Vector2( 870, 264 )
script = ExtResource( 6 )
global_id = "cocina_delante_pegatinas"
esc_script = "res://gymkhana/rooms/turno_cocina/cocina_delante/esc/pegatinas.esc"
combine_when_selected_action_is_in = [ ]
dialog_color = Color( 1, 1, 1, 1 )
tooltips = {
"action1": "cocina_delante_pegatinas_action1",
"action2": "cocina_delante_pegatinas_action2"
}
animations = null
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="pegatinas"]
position = Vector2( -33, -25 )
polygon = PoolVector2Array( -20, 43, 37, 46, 39, 87, 57, 86, 92, 84, 91, -16, 47, -17, -20, -17, -21, 26 )
[node name="ESCLocation" type="Position2D" parent="pegatinas"]
position = Vector2( -99, 213 )
script = ExtResource( 5 )

View File

@@ -25,7 +25,7 @@
set_gui_visible false
walk_block player puerta_cocina_start
set_angle player 180
say current_player "Alo Uli!"
say current_player hello_start_game:"Alo Uli!"
set_gui_visible true
accept_input ALL

View File

@@ -0,0 +1,5 @@
:action1
say_random current_player turno_cocina_pegatinas 5 1
:action2
say eneko_smoking pegatinas_action2_eneko_smoking_say:"Eh! las pegatinas no se tocan"

View File

@@ -0,0 +1,6 @@
keys,es
turno_cocina_pegatinas_1,Hay muchas que molan!!
turno_cocina_pegatinas_2,Algunas no las entiendo.
turno_cocina_pegatinas_3,Alguna ya la conocia.
turno_cocina_pegatinas_4,Ya casi no se ve la ventana.
turno_cocina_pegatinas_5,La proxima vez que venga traere alguna pegatina.
1 keys es
2 turno_cocina_pegatinas_1 Hay muchas que molan!!
3 turno_cocina_pegatinas_2 Algunas no las entiendo.
4 turno_cocina_pegatinas_3 Alguna ya la conocia.
5 turno_cocina_pegatinas_4 Ya casi no se ve la ventana.
6 turno_cocina_pegatinas_5 La proxima vez que venga traere alguna pegatina.

View File

@@ -0,0 +1,13 @@
keys,en,fr,es
hello_start_game,Alo Uli!,Alo Uli!,Alo Uli!
frontal_action3,Admire,Admire,Admirar
frontal_action3_say,"It's my lifelong headlight, I love it","C'est ma lampe frontale de toujours, je l'adore","Es mi frontal de toda la vida, le tengo cariño"
frontal_action4,Use,Utiliser,Usar
pegatinas_action2_eneko_smoking_say,Eh! las pegatinas no se tocan,Eh! las pegatinas no se tocan,Eh! las pegatinas no se tocan
cocina_delante_pegatinas_action1,,,"Observar pegatinas"
cocina_delante_pegatinas_action2,,,"Coger una pegatina"
cocina_delante_eneko_smoking_action1,,,"Observar sujeto"
cocina_delante_eneko_smoking_action2,,,"Hablar"
cocina_delante_puerta_detras_action1,,,"Ir detrás"
cocina_delante_puerta_despensa_action1,,,"Bajar a la despensa"
cocina_delante_puerta_cocina_action1,,,"Entrar en la cocina"
1 keys en fr es
2 hello_start_game Alo Uli! Alo Uli! Alo Uli!
3 frontal_action3 Admire Admire Admirar
4 frontal_action3_say It's my lifelong headlight, I love it C'est ma lampe frontale de toujours, je l'adore Es mi frontal de toda la vida, le tengo cariño
5 frontal_action4 Use Utiliser Usar
6 pegatinas_action2_eneko_smoking_say Eh! las pegatinas no se tocan Eh! las pegatinas no se tocan Eh! las pegatinas no se tocan
7 cocina_delante_pegatinas_action1 Observar pegatinas
8 cocina_delante_pegatinas_action2 Coger una pegatina
9 cocina_delante_eneko_smoking_action1 Observar sujeto
10 cocina_delante_eneko_smoking_action2 Hablar
11 cocina_delante_puerta_detras_action1 Ir detrás
12 cocina_delante_puerta_despensa_action1 Bajar a la despensa
13 cocina_delante_puerta_cocina_action1 Entrar en la cocina