diff --git a/docs/examples.rst b/docs/examples.rst index 27617c3..d3b4480 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -91,7 +91,7 @@ Translations ~~~~~~~~~~~~ Use ``_("...")`` to mark strings as translatable. You can put a comment for -translators on the line above. +translators on the line above if needed. .. code-block:: @@ -100,6 +100,18 @@ translators on the line above. label: _("Hello, world!"); } +Use ``C_("context", "...")`` to add a *message context* to a string to +disambiguate it, in case the same string appears in different places. Remember, +two strings might be the same in one language but different in another depending +on context. + +.. code-block:: + + Gtk.Label label { + /* Translators: This is a section in the preferences window */ + label: C_("preferences window", "Hello, world!"); + } + Referencing objects by ID ~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/gtkblueprinttool/ast.py b/gtkblueprinttool/ast.py index 886369d..9b755bc 100644 --- a/gtkblueprinttool/ast.py +++ b/gtkblueprinttool/ast.py @@ -275,7 +275,6 @@ class Property(AstNode): def emit_xml(self, xml: XmlEmitter): values = self.children[Value] value = values[0] if len(values) == 1 else None - translatable = isinstance(value, TranslatedStringValue) bind_flags = [] if self.tokens["sync_create"]: @@ -286,12 +285,14 @@ class Property(AstNode): props = { "name": self.tokens["name"], - "translatable": "true" if translatable else None, "bind-source": self.tokens["bind_source"], "bind-property": self.tokens["bind_property"], "bind-flags": bind_flags_str, } + if isinstance(value, TranslatedStringValue): + props = { **props, **value.attrs } + if len(self.children[Object]) == 1: xml.start_tag("property", **props) self.children[Object][0].emit_xml(xml) @@ -300,10 +301,7 @@ class Property(AstNode): xml.put_self_closing("property", **props) else: xml.start_tag("property", **props) - if translatable: - xml.put_text(value.string) - else: - value.emit_xml(xml) + value.emit_xml(xml) xml.end_tag() @@ -357,11 +355,14 @@ class Value(ast.AstNode): class TranslatedStringValue(Value): @property - def string(self): - return self.tokens["value"] + def attrs(self): + attrs = { "translatable": "true" } + if "context" in self.tokens: + attrs["context"] = self.tokens["context"] + return attrs - def emit_xml(self, xml): - raise CompilerBugError("TranslatedStringValues must be handled by the parent AST node") + def emit_xml(self, xml: XmlEmitter): + xml.put_text(self.tokens["value"]) class LiteralValue(Value): @@ -470,16 +471,13 @@ class BaseAttribute(AstNode): def emit_xml(self, xml: XmlEmitter): value = self.children[Value][0] - translatable = isinstance(value, TranslatedStringValue) - attrs = { - self.attr_name: self.tokens["name"], - "translatable": "true" if translatable else None - } + attrs = { self.attr_name: self.tokens["name"] } + + if isinstance(value, TranslatedStringValue): + attrs = { **attrs, **value.attrs } + xml.start_tag(self.tag_name, **attrs) - if translatable: - xml.put_text(value.string) - else: - value.emit_xml(xml) + value.emit_xml(xml) xml.end_tag() diff --git a/gtkblueprinttool/extensions/gtk_string_list.py b/gtkblueprinttool/extensions/gtk_string_list.py index db92331..1f6b68a 100644 --- a/gtkblueprinttool/extensions/gtk_string_list.py +++ b/gtkblueprinttool/extensions/gtk_string_list.py @@ -48,12 +48,9 @@ class Item(AstNode): def emit_xml(self, xml: XmlEmitter): value = self.children[Value][0] - translatable = isinstance(value, TranslatedStringValue) - xml.start_tag("item", translatable="true" if translatable else None) - if translatable: - xml.put_text(value.string) - else: - value.emit_xml(xml) + attrs = value.attrs if isinstance(value, TranslatedStringValue) else {} + xml.start_tag("item", **attrs) + value.emit_xml(xml) xml.end_tag() diff --git a/gtkblueprinttool/parser_utils.py b/gtkblueprinttool/parser_utils.py index ce9687d..ec10ebd 100644 --- a/gtkblueprinttool/parser_utils.py +++ b/gtkblueprinttool/parser_utils.py @@ -60,11 +60,22 @@ flags_value = Group( translated_string = Group( ast.TranslatedStringValue, - Sequence( - Keyword("_"), - OpenParen(), - UseQuoted("value").expected("a quoted string"), - CloseParen().expected("`)`"), + AnyOf( + Sequence( + Keyword("_"), + OpenParen(), + UseQuoted("value").expected("a quoted string"), + CloseParen().expected("`)`"), + ), + Sequence( + Keyword("C_"), + OpenParen(), + UseQuoted("context").expected("a quoted string"), + Comma(), + UseQuoted("value").expected("a quoted string"), + Optional(Comma()), + CloseParen().expected("`)`"), + ), ), ) diff --git a/tests/samples/translated.blp b/tests/samples/translated.blp index c1cde19..d926754 100644 --- a/tests/samples/translated.blp +++ b/tests/samples/translated.blp @@ -3,3 +3,6 @@ using Gtk 4.0; Label { label: _("Hello, world!"); } +Label { + label: C_("translation context", "Hello"); +} diff --git a/tests/samples/translated.ui b/tests/samples/translated.ui index 19cf381..6f84d40 100644 --- a/tests/samples/translated.ui +++ b/tests/samples/translated.ui @@ -4,4 +4,7 @@ Hello, world! + + Hello +