build system: add target for normalizing all .po files to one format

Pulling and integrating the translation updates from Transifex
will need automation. In order to keep the resulting diffs as
small as possible all files will have to use a unified format.

This code re-writes all po files in that format.
This commit is contained in:
Moritz Bunkus 2016-02-28 10:49:57 +01:00
parent de075bbc8c
commit 9bb97976d6
3 changed files with 149 additions and 61 deletions

View File

@ -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

View File

@ -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

130
rake.d/po.rb Normal file
View File

@ -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