You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-04 12:00:25 +00:00
POT Generator: Add support for TRANSLATORS: and NO_TRANSLATE comments
This commit is contained in:
@@ -51,6 +51,10 @@ Error GDScriptEditorTranslationParserPlugin::parse_file(const String &p_path, Ve
|
||||
|
||||
ids = r_ids;
|
||||
ids_ctx_plural = r_ids_ctx_plural;
|
||||
|
||||
ids_comment.clear();
|
||||
ids_ctx_plural_comment.clear();
|
||||
|
||||
Ref<GDScript> gdscript = loaded_res;
|
||||
String source_code = gdscript->get_source_code();
|
||||
|
||||
@@ -62,18 +66,90 @@ Error GDScriptEditorTranslationParserPlugin::parse_file(const String &p_path, Ve
|
||||
err = analyzer.analyze();
|
||||
ERR_FAIL_COND_V_MSG(err, err, "Failed to analyze GDScript with GDScriptAnalyzer.");
|
||||
|
||||
comment_data = &parser.comment_data;
|
||||
|
||||
// Traverse through the parsed tree from GDScriptParser.
|
||||
GDScriptParser::ClassNode *c = parser.get_tree();
|
||||
_traverse_class(c);
|
||||
|
||||
comment_data = nullptr;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
void GDScriptEditorTranslationParserPlugin::get_comments(Vector<String> *r_ids_comment, Vector<String> *r_ids_ctx_plural_comment) {
|
||||
r_ids_comment->append_array(ids_comment);
|
||||
r_ids_ctx_plural_comment->append_array(ids_ctx_plural_comment);
|
||||
}
|
||||
|
||||
bool GDScriptEditorTranslationParserPlugin::_is_constant_string(const GDScriptParser::ExpressionNode *p_expression) {
|
||||
ERR_FAIL_NULL_V(p_expression, false);
|
||||
return p_expression->is_constant && p_expression->reduced_value.is_string();
|
||||
}
|
||||
|
||||
String GDScriptEditorTranslationParserPlugin::_parse_comment(int p_line, bool &r_skip) const {
|
||||
// Parse inline comment.
|
||||
if (comment_data->has(p_line)) {
|
||||
const String stripped_comment = comment_data->get(p_line).comment.trim_prefix("#").strip_edges();
|
||||
|
||||
if (stripped_comment.begins_with("TRANSLATORS:")) {
|
||||
return stripped_comment.trim_prefix("TRANSLATORS:").strip_edges(true, false);
|
||||
}
|
||||
if (stripped_comment == "NO_TRANSLATE" || stripped_comment.begins_with("NO_TRANSLATE:")) {
|
||||
r_skip = true;
|
||||
return String();
|
||||
}
|
||||
}
|
||||
|
||||
// Parse multiline comment.
|
||||
String multiline_comment;
|
||||
for (int line = p_line - 1; comment_data->has(line) && comment_data->get(line).new_line; line--) {
|
||||
const String stripped_comment = comment_data->get(line).comment.trim_prefix("#").strip_edges();
|
||||
|
||||
if (stripped_comment.is_empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (multiline_comment.is_empty()) {
|
||||
multiline_comment = stripped_comment;
|
||||
} else {
|
||||
multiline_comment = stripped_comment + "\n" + multiline_comment;
|
||||
}
|
||||
|
||||
if (stripped_comment.begins_with("TRANSLATORS:")) {
|
||||
return multiline_comment.trim_prefix("TRANSLATORS:").strip_edges(true, false);
|
||||
}
|
||||
if (stripped_comment == "NO_TRANSLATE" || stripped_comment.begins_with("NO_TRANSLATE:")) {
|
||||
r_skip = true;
|
||||
return String();
|
||||
}
|
||||
}
|
||||
|
||||
return String();
|
||||
}
|
||||
|
||||
void GDScriptEditorTranslationParserPlugin::_add_id(const String &p_id, int p_line) {
|
||||
bool skip = false;
|
||||
const String comment = _parse_comment(p_line, skip);
|
||||
if (skip) {
|
||||
return;
|
||||
}
|
||||
|
||||
ids->push_back(p_id);
|
||||
ids_comment.push_back(comment);
|
||||
}
|
||||
|
||||
void GDScriptEditorTranslationParserPlugin::_add_id_ctx_plural(const Vector<String> &p_id_ctx_plural, int p_line) {
|
||||
bool skip = false;
|
||||
const String comment = _parse_comment(p_line, skip);
|
||||
if (skip) {
|
||||
return;
|
||||
}
|
||||
|
||||
ids_ctx_plural->push_back(p_id_ctx_plural);
|
||||
ids_ctx_plural_comment.push_back(comment);
|
||||
}
|
||||
|
||||
void GDScriptEditorTranslationParserPlugin::_traverse_class(const GDScriptParser::ClassNode *p_class) {
|
||||
for (int i = 0; i < p_class->members.size(); i++) {
|
||||
const GDScriptParser::ClassNode::Member &m = p_class->members[i];
|
||||
@@ -253,7 +329,7 @@ void GDScriptEditorTranslationParserPlugin::_assess_assignment(const GDScriptPar
|
||||
|
||||
if (assignee_name != StringName() && assignment_patterns.has(assignee_name) && _is_constant_string(p_assignment->assigned_value)) {
|
||||
// If the assignment is towards one of the extract patterns (text, tooltip_text etc.), and the value is a constant string, we collect the string.
|
||||
ids->push_back(p_assignment->assigned_value->reduced_value);
|
||||
_add_id(p_assignment->assigned_value->reduced_value, p_assignment->assigned_value->start_line);
|
||||
} else if (assignee_name == fd_filters) {
|
||||
// Extract from `get_node("FileDialog").filters = <filter array>`.
|
||||
_extract_fd_filter_array(p_assignment->assigned_value);
|
||||
@@ -287,7 +363,7 @@ void GDScriptEditorTranslationParserPlugin::_assess_call(const GDScriptParser::C
|
||||
}
|
||||
}
|
||||
if (extract_id_ctx_plural) {
|
||||
ids_ctx_plural->push_back(id_ctx_plural);
|
||||
_add_id_ctx_plural(id_ctx_plural, p_call->start_line);
|
||||
}
|
||||
} else if (function_name == trn_func || function_name == atrn_func) {
|
||||
// Extract from `tr_n(id, plural, n, ctx)` or `atr_n(id, plural, n, ctx)`.
|
||||
@@ -307,20 +383,20 @@ void GDScriptEditorTranslationParserPlugin::_assess_call(const GDScriptParser::C
|
||||
}
|
||||
}
|
||||
if (extract_id_ctx_plural) {
|
||||
ids_ctx_plural->push_back(id_ctx_plural);
|
||||
_add_id_ctx_plural(id_ctx_plural, p_call->start_line);
|
||||
}
|
||||
} else if (first_arg_patterns.has(function_name)) {
|
||||
if (!p_call->arguments.is_empty() && _is_constant_string(p_call->arguments[0])) {
|
||||
ids->push_back(p_call->arguments[0]->reduced_value);
|
||||
_add_id(p_call->arguments[0]->reduced_value, p_call->arguments[0]->start_line);
|
||||
}
|
||||
} else if (second_arg_patterns.has(function_name)) {
|
||||
if (p_call->arguments.size() > 1 && _is_constant_string(p_call->arguments[1])) {
|
||||
ids->push_back(p_call->arguments[1]->reduced_value);
|
||||
_add_id(p_call->arguments[1]->reduced_value, p_call->arguments[1]->start_line);
|
||||
}
|
||||
} else if (function_name == fd_add_filter) {
|
||||
// Extract the 'JPE Images' in this example - get_node("FileDialog").add_filter("*.jpg; JPE Images").
|
||||
if (!p_call->arguments.is_empty()) {
|
||||
_extract_fd_filter_string(p_call->arguments[0]);
|
||||
_extract_fd_filter_string(p_call->arguments[0], p_call->arguments[0]->start_line);
|
||||
}
|
||||
} else if (function_name == fd_set_filter) {
|
||||
// Extract from `get_node("FileDialog").set_filters(<filter array>)`.
|
||||
@@ -330,12 +406,12 @@ void GDScriptEditorTranslationParserPlugin::_assess_call(const GDScriptParser::C
|
||||
}
|
||||
}
|
||||
|
||||
void GDScriptEditorTranslationParserPlugin::_extract_fd_filter_string(const GDScriptParser::ExpressionNode *p_expression) {
|
||||
void GDScriptEditorTranslationParserPlugin::_extract_fd_filter_string(const GDScriptParser::ExpressionNode *p_expression, int p_line) {
|
||||
// Extract the name in "extension ; name".
|
||||
if (_is_constant_string(p_expression)) {
|
||||
PackedStringArray arr = p_expression->reduced_value.operator String().split(";", true);
|
||||
ERR_FAIL_COND_MSG(arr.size() != 2, "Argument for setting FileDialog has bad format.");
|
||||
ids->push_back(arr[1].strip_edges());
|
||||
_add_id(arr[1].strip_edges(), p_line);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,7 +431,7 @@ void GDScriptEditorTranslationParserPlugin::_extract_fd_filter_array(const GDScr
|
||||
|
||||
if (array_node) {
|
||||
for (int i = 0; i < array_node->elements.size(); i++) {
|
||||
_extract_fd_filter_string(array_node->elements[i]);
|
||||
_extract_fd_filter_string(array_node->elements[i], array_node->elements[i]->start_line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user