diff --git a/openformats/formats/yaml/utils.py b/openformats/formats/yaml/utils.py index 1cfcb7c0..22826dca 100644 --- a/openformats/formats/yaml/utils.py +++ b/openformats/formats/yaml/utils.py @@ -142,13 +142,19 @@ def _is_custom_tag(self, tag): Detect custom tags, like: `foo: !bar test` `foo: !xml "Bar"` + + The name of the custom tag can have any of the following characters: + `a-z`, `A-Z`, `0-9`, `_`, `.`, `:`, `-`. + In any other case, we return `False`. + Built-in types, indicated by a `!!` prefix, will not be matched. We can't preserve the information whether a built-in tag like `!!str` was used for a value since the PyYAML library will tag such entries with the built-in identifier. For example `tag:yaml.org,2002:str`, not `!!str`. """ - return re.match(ensure_unicode(r'^[\![a-zA-Z_]*]*$'), + + return re.match(ensure_unicode(r'^\![a-zA-Z0-9_:.\-]*$'), tag, re.IGNORECASE) @@ -222,6 +228,8 @@ def construct_mapping(self, node, deep=True): and self._is_custom_tag(value_node.tag) ): tag = six.text_type(value_node.tag) + # remove the exclamation mark from the tag + tag = tag[1:] if tag.startswith('!') else tag value = Node(value, start, end, style, tag) pairs.append((key, value)) @@ -349,8 +357,9 @@ def generate_yaml_dict(self, stringset): yaml_dict, keys, flags, se.string.get(rule), tag=None, ) else: + tag = '!' + se.context if se.context else se.context self._insert_translation_in_dict( - yaml_dict, keys, flags, se.string, tag=se.context, + yaml_dict, keys, flags, se.string, tag=tag, ) return yaml_dict diff --git a/openformats/formats/yaml/yaml.py b/openformats/formats/yaml/yaml.py index b6d3bd5f..0e4c7295 100644 --- a/openformats/formats/yaml/yaml.py +++ b/openformats/formats/yaml/yaml.py @@ -404,7 +404,8 @@ def _compile_from_template(self, template, stringset, **kwargs): # it and apply a space afterwards so it doesn't get merged with the # string if string.context: - transcriber.add(string.context) + # add an exclamation mark to the context to make it a tag + transcriber.add('!' + string.context) transcriber.add(' ') transcriber.add(translation) transcriber.skip(len(string.template_replacement)) diff --git a/openformats/tests/formats/yaml/files/1_el.yml b/openformats/tests/formats/yaml/files/1_el.yml index ae380ac4..45e24e9b 100644 --- a/openformats/tests/formats/yaml/files/1_el.yml +++ b/openformats/tests/formats/yaml/files/1_el.yml @@ -77,6 +77,13 @@ hello: "el:World" # Translatable number: !!int 123 # Should ignore bin: !!binary aGVsbG8= # Should ignore +# Custom tags with numbers and symbols +context_string: !cs:fd-94_fd.dot. "el:context string" +verbim_context_string: !context:t5-46_qa "el:verbim context string" +context_on_nested_map: + first: !first_context:54KJFLA95KJ4 "el:context in nested map" + second: !second_context:FDKJ40DK "el:context in nested map" + # Test with non-ASCII keys #σχόλιο σχόλιο: "el:κείμενο" diff --git a/openformats/tests/formats/yaml/files/1_en.yml b/openformats/tests/formats/yaml/files/1_en.yml index 7d92dfcb..b751cca8 100644 --- a/openformats/tests/formats/yaml/files/1_en.yml +++ b/openformats/tests/formats/yaml/files/1_en.yml @@ -80,6 +80,13 @@ hello: !!str World # Translatable number: !!int 123 # Should ignore bin: !!binary aGVsbG8= # Should ignore +# Custom tags with numbers and symbols +context_string: !cs:fd-94_fd.dot. "context string" +verbim_context_string: ! "verbim context string" +context_on_nested_map: + first: !first_context:54KJFLA95KJ4 "context in nested map" + second: !second_context:FDKJ40DK "context in nested map" + # Test with non-ASCII keys #σχόλιο σχόλιο: κείμενο diff --git a/openformats/tests/formats/yaml/files/1_en_exported.yml b/openformats/tests/formats/yaml/files/1_en_exported.yml index 7a0af47d..4e324640 100644 --- a/openformats/tests/formats/yaml/files/1_en_exported.yml +++ b/openformats/tests/formats/yaml/files/1_en_exported.yml @@ -77,6 +77,13 @@ hello: World # Translatable number: !!int 123 # Should ignore bin: !!binary aGVsbG8= # Should ignore +# Custom tags with numbers and symbols +context_string: !cs:fd-94_fd.dot. "context string" +verbim_context_string: !context:t5-46_qa "verbim context string" +context_on_nested_map: + first: !first_context:54KJFLA95KJ4 "context in nested map" + second: !second_context:FDKJ40DK "context in nested map" + # Test with non-ASCII keys #σχόλιο σχόλιο: κείμενο diff --git a/openformats/tests/formats/yaml/files/1_en_exported_without_template.yml b/openformats/tests/formats/yaml/files/1_en_exported_without_template.yml index cda13ac4..2a21c55f 100644 --- a/openformats/tests/formats/yaml/files/1_en_exported_without_template.yml +++ b/openformats/tests/formats/yaml/files/1_en_exported_without_template.yml @@ -39,6 +39,11 @@ alias_key: foo: !test 'bar' bar: !xml "foo bar" hello: World +context_string: !cs:fd-94_fd.dot. "context string" +verbim_context_string: !context:t5-46_qa "verbim context string" +context_on_nested_map: + first: "context in nested map" + second: "context in nested map" σχόλιο: κείμενο emojis: \uD83D\uDC40 🏹🍍🍍 \U0001F418 anchor_with_label: diff --git a/openformats/tests/formats/yaml/files/1_tpl.yml b/openformats/tests/formats/yaml/files/1_tpl.yml index f9931de2..0a5efd5d 100644 --- a/openformats/tests/formats/yaml/files/1_tpl.yml +++ b/openformats/tests/formats/yaml/files/1_tpl.yml @@ -65,12 +65,19 @@ alias_key: - ddc3cfcedcf1686d9e3ba6b99a0d091b_tr # Custom tags -foo: 3e4000f6f4cd8bb27db6fb82e1b50bb4_tr # Should treat as string and ignore leading spaces -bar: 75ce597a505a4faf6369b66b885926c8_tr # Also a string +foo: 023503fb466f78932b77209b6581156e_tr # Should treat as string and ignore leading spaces +bar: fac8140a2ec031af14bc758e73f59017_tr # Also a string hello: b0ed9cf22c0a5186d1c5b483a910dd33_tr # Translatable number: !!int 123 # Should ignore bin: !!binary aGVsbG8= # Should ignore +# Custom tags with numbers and symbols +context_string: 17d854ee46fe3d3bc91fadb4cf4df426_tr +verbim_context_string: 0a3c1ae205b2c0d09ab69ab540e481f2_tr +context_on_nested_map: + first: 95175e30d6fbfe0f658e75919cd4982c_tr + second: dce391c231a7ad7fef9e6cc0ddcbf549_tr + # Test with non-ASCII keys #σχόλιο σχόλιο: 8687f34a9bf89770b456b48ad2395788_tr diff --git a/openformats/tests/formats/yaml/test_yaml.py b/openformats/tests/formats/yaml/test_yaml.py index d547796b..cec516ec 100644 --- a/openformats/tests/formats/yaml/test_yaml.py +++ b/openformats/tests/formats/yaml/test_yaml.py @@ -144,7 +144,7 @@ def test_openstring_attributes(self): self.assertEqual(test_string.flags, '') content_string = strings[1] - self.assertEqual(content_string.context, '!tag') + self.assertEqual(content_string.context, 'tag') self.assertEqual(content_string.flags, "'") def test_parse_duplicate_keys(self): diff --git a/openformats/tests/formats/yamlinternationalization/files/1_el.yml b/openformats/tests/formats/yamlinternationalization/files/1_el.yml index 8a76cc8c..7f45b6d8 100644 --- a/openformats/tests/formats/yamlinternationalization/files/1_el.yml +++ b/openformats/tests/formats/yamlinternationalization/files/1_el.yml @@ -100,3 +100,10 @@ en: anchor_mapping: &another_anchor one: el:one other: el:other + + # context + context_string: !cs:fd-94_fd.dot. "el:context string" + verbim_context_string: !context:t5-46_qa "el:verbim context string" + context_on_nested_map: + first: !first_context:54KJFLA95KJ4 "el:context in nested map" + second: !second_context:FDKJ40DK "el:context in nested map" diff --git a/openformats/tests/formats/yamlinternationalization/files/1_en.yml b/openformats/tests/formats/yamlinternationalization/files/1_en.yml index 8f7496ca..deb2a70e 100644 --- a/openformats/tests/formats/yamlinternationalization/files/1_en.yml +++ b/openformats/tests/formats/yamlinternationalization/files/1_en.yml @@ -104,3 +104,10 @@ en: anchor_mapping: &another_anchor one: one other: other + + # context + context_string: !cs:fd-94_fd.dot. "context string" + verbim_context_string: ! "verbim context string" + context_on_nested_map: + first: !first_context:54KJFLA95KJ4 "context in nested map" + second: !second_context:FDKJ40DK "context in nested map" diff --git a/openformats/tests/formats/yamlinternationalization/files/1_en_exported.yml b/openformats/tests/formats/yamlinternationalization/files/1_en_exported.yml index 6c0fd992..d603d85e 100644 --- a/openformats/tests/formats/yamlinternationalization/files/1_en_exported.yml +++ b/openformats/tests/formats/yamlinternationalization/files/1_en_exported.yml @@ -100,3 +100,10 @@ en: anchor_mapping: &another_anchor one: one other: other + + # context + context_string: !cs:fd-94_fd.dot. "context string" + verbim_context_string: !context:t5-46_qa "verbim context string" + context_on_nested_map: + first: !first_context:54KJFLA95KJ4 "context in nested map" + second: !second_context:FDKJ40DK "context in nested map" diff --git a/openformats/tests/formats/yamlinternationalization/files/1_en_exported_without_template.yml b/openformats/tests/formats/yamlinternationalization/files/1_en_exported_without_template.yml index 68ea80f7..1595af46 100644 --- a/openformats/tests/formats/yamlinternationalization/files/1_en_exported_without_template.yml +++ b/openformats/tests/formats/yamlinternationalization/files/1_en_exported_without_template.yml @@ -59,3 +59,8 @@ en: anchor_mapping: one: one other: other + context_string: !cs:fd-94_fd.dot. "context string" + verbim_context_string: !context:t5-46_qa "verbim context string" + context_on_nested_map: + first: "context in nested map" + second: "context in nested map" diff --git a/openformats/tests/formats/yamlinternationalization/files/1_tpl.yml b/openformats/tests/formats/yamlinternationalization/files/1_tpl.yml index 656597e7..85943df5 100644 --- a/openformats/tests/formats/yamlinternationalization/files/1_tpl.yml +++ b/openformats/tests/formats/yamlinternationalization/files/1_tpl.yml @@ -90,3 +90,10 @@ en: anchor_mapping: &another_anchor 798cf4a4e275a90e80b0aac837f06793_pl + + # context + context_string: 17d854ee46fe3d3bc91fadb4cf4df426_tr + verbim_context_string: 0a3c1ae205b2c0d09ab69ab540e481f2_tr + context_on_nested_map: + first: 95175e30d6fbfe0f658e75919cd4982c_tr + second: dce391c231a7ad7fef9e6cc0ddcbf549_tr