diff --git a/Rakefile b/Rakefile index 77f8cc9b1..07a845ff2 100755 --- a/Rakefile +++ b/Rakefile @@ -40,6 +40,7 @@ require_relative "rake.d/target" require_relative "rake.d/application" require_relative "rake.d/library" require_relative "rake.d/format_string_verifier" +require_relative "rake.d/po" require_relative "rake.d/tarball" require_relative 'rake.d/gtest' if $have_gtest @@ -73,6 +74,9 @@ def setup_globals $all_sources = $source_directories.collect { |dir| FileList[ "#{dir}/**/*.c", "#{dir}/**/*.cpp" ].to_a }.flatten.sort $all_headers = $source_directories.collect { |dir| FileList[ "#{dir}/**/*.h", ].to_a }.flatten.sort $all_objects = $all_sources.collect { |file| file.ext('o') } + $all_app_po_files = FileList["po/*.po"].to_a.sort + $all_man_po_files = FileList["doc/man/po4a/po/*.po"].to_a.sort + $all_po_files = $all_app_po_files + $all_man_po_files $gui_ui_files = FileList["src/mkvtoolnix-gui/forms/**/*.ui"].to_a $gui_ui_h_files = $gui_ui_files.collect { |file| file.ext 'h' } @@ -451,6 +455,15 @@ EOT exit 1 if !verify_format_strings(languages) end + $all_po_files.each do |po_file| + task "normalize-po-#{po_file}" do + normalize_po po_file + end + end + + desc "Normalize all .po files to a standard format" + task "normalize-po" => $all_po_files.map { |e| "translations:normalize-po-#{e}" } + [ :applications, :manpages ].each { |type| task type => $translations[type] } task :qt => FileList[ "#{$top_srcdir }/po/qt/*.ts" ].collect { |file| file.ext 'qm' } @@ -486,7 +499,9 @@ EOT exit exit_code end - adjust_to_poedit_style tmp_file, po, language + FileUtils.move tmp_file, po + + normalize_po po end end end @@ -494,10 +509,8 @@ EOT desc "Update the man pages' translation files" task :manpages do runq " PO4A doc/man/po4a/po4a.cfg", "#{c(:PO4A)} #{c(:PO4A_FLAGS)} --msgmerge-opt=--no-wrap doc/man/po4a/po4a.cfg" - %w{nl uk zh_CN}.each do |language| - name = "doc/man/po4a/po/#{language}.po" - FileUtils.cp name, "#{name}.tmp" - adjust_to_poedit_style "#{name}.tmp", name, language + $all_man_po_files.each do |po_file| + normalize_po po_file end end diff --git a/rake.d/helpers.rb b/rake.d/helpers.rb index ccd771fe1..e46af61f2 100644 --- a/rake.d/helpers.rb +++ b/rake.d/helpers.rb @@ -1,3 +1,4 @@ +# coding: utf-8 $use_tempfile_for_run = defined?(RUBY_PLATFORM) && /mingw/i.match(RUBY_PLATFORM) require "tempfile" require "fileutils" @@ -148,62 +149,6 @@ def install_data(destination, *files) end end -def adjust_to_poedit_style(in_name, out_name, language) - File.open(out_name, "w") do |out| - lines = IO.readlines(in_name).collect { |line| line.chomp.gsub(/\r/, '') }.reject { |line| /^\s*$/.match(line) } - state = :initial - previous_state = :initial - sources = [] - one_source = !$unwrapped_po.include?(language) && !$po_multiple_sources.include?(language) - - lines.each do |line| - previous_state = state - - if /^#~/.match(line) - state = :removed - elsif /^\"/.match(line) - state = :string - elsif /^msgstr/.match(line) - state = :msgstr - elsif /^#[^:]/.match(line) - state = :comment - else - state = :other - end - - if /^(?:#,|msgid)/.match(line) - if one_source - sources.each { |source| out.puts "#: #{source}" } - else - while !sources.empty? - new_line = "#:" - first_in_line = true - while !sources.empty? && (first_in_line || ((new_line.length + sources[0].length + 1) < 80)) - new_line += " " + sources.shift - first_in_line = false - end - out.puts new_line - end - end - - sources = [] - end - - out.puts if /^#(?:,|:|\.|\s|~\s+msgid)/.match(line) && [:removed, :string, :msgstr].include?(previous_state) - - if /^#:/.match(line) - sources += line.gsub(/^#:\s*/, '').split(/\s+/) - else - out.puts line - end - end - - out.puts unless %w{es it}.include?(language) - end - - File.unlink in_name -end - def remove_files_by_patters patterns verbose = ENV['V'].to_bool diff --git a/rake.d/po.rb b/rake.d/po.rb new file mode 100644 index 000000000..9b25ea465 --- /dev/null +++ b/rake.d/po.rb @@ -0,0 +1,130 @@ +# coding: utf-8 + +def format_string_for_po str + return '"' + str.gsub(/"/, '\"') + '"' unless /\\n./.match(str) + + ([ '""' ] + str.split(/(?<=\\n)/).map { |part| '"' + part.gsub(/"/, '\"') + '"' }).join("\n") +end + +def unformat_string_for_po str + str.gsub(/^"|"$/, '').gsub(/\\"/, '"') +end + +def read_po file_name + items = [ { comments: [] } ] + msgtype = nil + line_no = 0 + + add_line = lambda do |type, to_add| + items.last[type] ||= [] + items.last[type] += to_add if to_add.is_a?(Array) + items.last[type] << to_add if to_add.is_a?(String) + end + + IO.readlines(file_name).each do |line| + line_no += 1 + line.chomp! + + if line.empty? + items << {} unless items.last.keys.empty? + msgtype = nil + + elsif items.size == 1 + add_line.call :comments, line + + elsif /^#:\s*(.+)/.match(line) + add_line.call :sources, $1.split(/\s+/) + + elsif /^#,\s*(.+)/.match(line) + add_line.call :flags, $1.split(/,\s*/) + + elsif /^#\./.match(line) + add_line.call :instructions, line + + elsif /^#~/.match(line) + add_line.call :obsolete, line + + elsif /^#\|/.match(line) + add_line.call :other, line + + elsif /^#\s/.match(line) + add_line.call :comments, line + + elsif /^ ( msgid(?:_plural)? | msgstr (?: \[ \d+ \])? ) \s* (.+)/x.match(line) + type, string = $1, $2 + msgtype = type.gsub(/\[.*/, '').to_sym + + items.last[msgtype] ||= [] + items.last[msgtype] << unformat_string_for_po(string) + + elsif /^"/.match(line) + fail "read_po: #{file_name}:#{line_no}: string entry without prior msgid/msgstr for »#{line}«" unless msgtype + items.last[msgtype].last << unformat_string_for_po(line) + + else + fail "read_po: #{file_name}:#{line_no}: unrecognized line type for »#{line}«" + + end + end + + items.pop if items.last.keys.empty? + + return items +end + +def write_po file_name, items + File.open(file_name, "w") do |file| + items.each do |item| + if item[:obsolete] + file.puts(item[:obsolete].join("\n")) + file.puts + next + end + + if item[:comments] + file.puts(item[:comments].join("\n")) + end + + if item[:instructions] + file.puts(item[:instructions].join("\n")) + end + + if item[:sources] + file.puts(item[:sources].map { |source| "#: #{source}" }.join("\n").gsub(/,$/, '')) + end + + if item[:flags] + file.puts("#, " + item[:flags].join(", ")) + end + + if item[:other] + file.puts(item[:other].join("\n")) + end + + if item[:msgid] + file.puts("msgid " + format_string_for_po(item[:msgid].first)) + end + + if item[:msgid_plural] + file.puts("msgid_plural " + format_string_for_po(item[:msgid_plural].first)) + end + + if item[:msgstr] + idx = 0 + + item[:msgstr].each do |msgstr| + suffix = item[:msgid_plural] ? "[#{idx}]" : "" + idx += 1 + file.puts("msgstr#{suffix} " + format_string_for_po(msgstr)) + end + end + + file.puts + end + end +end + +def normalize_po file + puts "NORMALIZE-PO #{file}" + write_po file, read_po(file) +end