-
Notifications
You must be signed in to change notification settings - Fork 20
Description
Description
Hi, first of all thank you for the Quest System plugin — it’s very helpful.
While using the built-in translation export with Godot 4.5, I ran into an issue where quest-related translations are correctly generated into .po files, but cannot be resolved at runtime using tr(), even though the keys match exactly.
After debugging, I found that this is caused by how EditorTranslationParserPlugin is currently used in the plugin.
Root Cause Analysis
In EditorTranslationParserPlugin._parse_file(), the plugin returns a PackedStringArray with three elements per property:
msgids.append("quest_%s/%s" % [res.id, property.name])
msgids.append("Quest ID: %s, property: %s" % [res.id, property.name])
msgids.append("quest_%s/%s_plural" % [res.id, property.name])However, in Godot’s translation pipeline:
- PackedStringArray[0] → msgid
- PackedStringArray[1] → msgctxt
- PackedStringArray[2] → msgid_plural
This causes Godot to automatically generate .po entries like:
msgctxt "Quest ID: 1, property: quest_description"
msgid "quest_1/quest_description"
msgid_plural "quest_1/quest_description_plural"
msgstr[0] ""Problem
Godot runtime (TranslationServer) does not support:
- msgctxt
- msgid_plural
- msgstr[n]
As a result, any entry generated this way is silently ignored at runtime, and tr("quest_1/quest_description") simply returns the key.
My fixed version:
translation_plugin.gd
## plugin version:
#func Wrong_parse_file(path: String) -> Array[PackedStringArray]:
#var res := ResourceLoader.load(path)
#if not res: return []
#if not res is Quest: return []
#
#var ret: Array[PackedStringArray] = []
#for property in res.get_script().get_script_property_list():
#var msgids: PackedStringArray = []
#if property.type != 4: continue # If the property is not a string, we skip it
#
## Here we check if the property is an exported variable
#if property.usage == PROPERTY_USAGE_SCRIPT_VARIABLE | PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR:
#msgids.append("quest_%s/%s"% [res.id, property.name]) # quest_1/quest_name
#msgids.append("Quest ID: %s, property: %s"% [res.id, property.name]) # quest_1/quest_objective
#msgids.append("quest_%s/%s_plural"% [res.id, property.name]) # quest_1/quest_description
#
#ret.append(msgids)
#
#return ret
## My version:
func _parse_file(path: String) -> Array[PackedStringArray]:
var res := ResourceLoader.load(path)
if not res or not res is Quest:
return []
var ret: Array[PackedStringArray] = []
for property in res.get_script().get_script_property_list():
if property.type != TYPE_STRING:
continue
if property.usage == PROPERTY_USAGE_SCRIPT_VARIABLE | PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR:
var msgids := PackedStringArray()
msgids.append("quest_%s/%s" % [res.id, property.name])
ret.append(msgids)
return retInformation
- Version of Godot affected: 4.5.1.stable
- Version of QuestSystem: 2.0.1

