arashm/PoParser

Creating new Po from existing Po raises NoMethodError

rod-murphy opened this issue · 3 comments

I'm trying to create a new Po object by adding entries from another Po object:

po1 = PoParser.parse_file('file.po')

po2 = PoParser::Po.new

po2 << po1.to_h

Where file.po looks like:

#
msgid ""
msgstr ""
"Project-Id-Version: VERSION\n"
"PO-Revision-Date: 2020-07-22 15:46+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE TEAM <EMAIL@ADDRESS>\n"
"Language: en\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. TRANSLATOR: This is used to categorise questions
msgctxt "Platform"
msgid "Assessment"
msgstr ""

#. TRANSLATOR: This is used to categorise questions
msgctxt "Platform"
msgid "Scores"
msgstr "Scores"

But get the following error:

NoMethodError: undefined method `map' for #<String:0x000000010e5675c0>
Did you mean?  tap
from /Users/rodmurphy/.rbenv/versions/2.6.0/lib/ruby/gems/2.6.0/gems/PoParser-3.2.5/lib/poparser/header.rb:97:in `convert_msgstr_to_hash'
     NoMethodError:
       undefined method `map' for #<String:0x0000000111652bf8>
       Did you mean?  tap

     # /Users/rodmurphy/.rbenv/versions/2.6.0/lib/ruby/gems/2.6.0/gems/PoParser-3.2.5/lib/poparser/header.rb:97:in `convert_msgstr_to_hash'
     # /Users/rodmurphy/.rbenv/versions/2.6.0/lib/ruby/gems/2.6.0/gems/PoParser-3.2.5/lib/poparser/header.rb:14:in `initialize'
     # /Users/rodmurphy/.rbenv/versions/2.6.0/lib/ruby/gems/2.6.0/gems/PoParser-3.2.5/lib/poparser/po.rb:199:in `new'
     # /Users/rodmurphy/.rbenv/versions/2.6.0/lib/ruby/gems/2.6.0/gems/PoParser-3.2.5/lib/poparser/po.rb:199:in `add_header_entry'
     # /Users/rodmurphy/.rbenv/versions/2.6.0/lib/ruby/gems/2.6.0/gems/PoParser-3.2.5/lib/poparser/po.rb:190:in `add_entry'
     # /Users/rodmurphy/.rbenv/versions/2.6.0/lib/ruby/gems/2.6.0/gems/PoParser-3.2.5/lib/poparser/po.rb:177:in `import_hash'
     # /Users/rodmurphy/.rbenv/versions/2.6.0/lib/ruby/gems/2.6.0/gems/PoParser-3.2.5/lib/poparser/po.rb:30:in `add'

The reason for this error is that the header object in po1 when PoParser::Po#to_h is called, is not getting exported in a manner that Po#add can understand. Note that I get the same error if I do po2 << po1.header.to_h

The trace is as follows:

It's this last resulting string that raises the error when attempting to create the header for the new Po object.

I'm not sure if this is the expected behaviour or whether my po file in incorrectly formatted?

What I'm really aiming to to here is to merge 2 po objects while keeping entries ordered alphabetically in the resulting po file, but the above is the simplest way to reproduce the bug.

I'm more than happy to create a PR assuming I've not missed something obvious.

It's nice to add the merge ability with entries or two po files. I never thought about this use case. I'll look into it later.
In the meantime can't this be done like this maybe?

po1 = PoParser.parse_file('file_1.po')
po2 = PoParser.parse_file('file_2.po')
entries = po1.entries.to_h.merge(po2.to_h)
# Sort entries?
po3 = PoParser::Po.new(path: 'file_3.po')
po3.entries << entries
po3.save_file

You probably don't want to do that and rather rely on the official gettext msgmerge utiliy for merging 2 po files. It does a lot more and is usually part of the process of a gettext based translation anyway.

Thanks for the quick replies @arashm and @dfherr.

Your suggestions will work, @arashm, however, this will not preserve the header. Similarly, I did have a solution where I determined the diffs from each of the hash representations of the files and either added or removed entries as necessary. As you allude to above, this results in a po file in which the entries are unsorted.

I guess I could remove all non-header entries from po1 and add the sorted resulting hash entries.

I wasn't aware of msgmerge, @dfherr. I'll give it a go, thanks.