wichert / lingua

Translation toolkit for Python
Other
46 stars 32 forks source link

multiple root nodes #14

Closed lugensa closed 10 years ago

lugensa commented 12 years ago

Expat stops extracting after reading the first root element.

    def test_multiple_root_nodes(self): 
        snippet = """\                                                                                                                                                                                              
                <metal:foo>
                  <dummy i18n:translate="">Foo</dummy>
                  <dummy i18n:translate="">Foo</dummy>
                </metal:foo>
                <metal:bla>
                  <dummy i18n:translate="">Bla</dummy>
                  <dummy i18n:translate="">Bla</dummy>
                </metal:bla>
                """
        self.assertEqual(self.extract(snippet),
                [
                    (2, None, u"Foo", []),          
                    (3, None, u"Foo", []),          
                    (6, None, u"Bla", []),          
                    (7, None, u"Bla", []),          
                 ])
wichert commented 12 years ago

lingua expects an XML document as input. What you are providing is an XML fragment, not a document, and as a result it fails to parse. Is there a special reason you can not restructure your input to be a valid XML document?

lugensa commented 12 years ago

Hmm it's just the way of how to define multiple macros in one file. I've added now a node around and it works but this feels still like a hack.

I think this should be at least be documented, so that there is a difference between Chameleon <= 1.99, Zope i18n extraction and lingua.

    def test_multiple_root_nodes(self): 
        snippet = """\
                <tal:def define="foo nothing">                                                                                                                                                                                              
                <metal:foo>
                  <dummy i18n:translate="">Foo</dummy>
                  <dummy i18n:translate="">Foo</dummy>
                </metal:foo>
                <metal:bla>
                  <dummy i18n:translate="">Bla</dummy>
                  <dummy i18n:translate="">Bla</dummy>
                </metal:bla>
                </tal:def>
                """
        self.assertEqual(self.extract(snippet),
                [
                    (3, None, u"Foo", []),          
                    (4, None, u"Foo", []),          
                    (7, None, u"Bla", []),          
                    (8, None, u"Bla", []),          
                 ])
wichert commented 12 years ago

If I remember correctly Chameleon 1.x would not be able to parse your file either since it also used an XML parser. Note that you can simplify your input a bit further: you do need to define any attributes on your root element since elements in the tal or metal namespaces never result in output. My macro templates usually look like this:

<tal:macros xmlns:tal="http://namespaces.zope.org/tal"
            xmlns:metal="http://namespaces.zope.org/metal">
  <metal:navtree define-macro="navtree">
    ....
  </metal:navtree>
</tal:macros>
lugensa commented 12 years ago

It worked with Chameleon 1.x. We had some old repoze.bfg apps witch are fully translated. I've tried it with

<tal:macros xmlns:tal="http://namespaces.zope.org/tal"
            xmlns:metal="http://namespaces.zope.org/metal">
  <metal:navtree define-macro="navtree">
    ....
  </metal:navtree>
</tal:macros>

but than i get an KeyError: "Macro does not exist: 'navbar'." And names is empty

>>> foo = pyramid.renderers.get_renderer('foo:templates/foo.pt').implementation()
>>> foo.macros.names
[]
wichert commented 12 years ago

My mistake - I mistyped the namespaces from memory. They should be http://xml.zope.org/namespaces/tal and http://xml.zope.org/namespaces/metal

lugensa commented 12 years ago

Ahh ok didn't knew that Chameleon is also checking namspaces :)

wichert commented 12 years ago

Chameleon has built-in defaults in case you do not declare namespaces yourself. However if you do declare them properly you must be careful to do it right :). Thecurrent version of lingua shares similar logic for the i18n namespace, but unlike Chameleon 2 it uses a full XML parser, which is why it has stricter requirements on input.

wichert commented 10 years ago

This works correctly in lingua 2. Note that your exact input will still not work since you did not set an i18n:domain, which is required for translation to work.