smugglys/translatomatic

View on GitHub
lib/translatomatic/resource_file/po.rb

Summary

Maintainability
A
1 hr
Test Coverage
require 'poparser'

module Translatomatic
  module ResourceFile
    # Property list resource file
    # @see https://en.wikipedia.org/wiki/Property_list
    class PO < Base
      # (see Base.extensions)
      def self.extensions
        %w[po pot]
      end

      # (see Base.key_value?)
      def self.key_value?
        true
      end

      # (see Base#set)
      def set(key, value)
        super(key, value)

        if @pomap.include?(key)
          po_property = @pomap[key]
          entry = po_property.entry
          if entry.plural?
            msgstr = entry.msgstr || []
            msgstr[po_property.msgstr_index] = value
            entry.msgstr = msgstr
          else
            entry.msgstr = value
          end
        else
          # new key, create po entry
          @po << {
            msgid: key,
            msgstr: value
          }
          entry = @po.entries[-1]
          add_entry(entry, :msgid, 0)
        end
      end

      # (see Base#save)
      def save(target = path, options = {})
        return unless @po
        add_created_by unless options[:no_created_by]
        target.write(@po.to_s)
      end

      private

      PO_DATE_FORMAT = '%Y-%M-%d %HH:%MM%Z'.freeze

      # used to index into PO msgstr[]
      # @private
      class PoProperty
        attr_reader :entry
        attr_reader :msgstr_index

        def initialize(entry, msgstr_index)
          @entry = entry
          @msgstr_index = msgstr_index
        end

        def value
          if entry.plural?
            entry.msgstr[msgstr_index]
          else
            entry.msgstr
          end
        end
      end

      def init
        @po = PoParser.parse('')
        @pomap = {}
      end

      def load
        @metadata.reset
        content = read_contents(@path)
        @po = PoParser.parse(content)
        init_pomap(@po)
        @properties = pomap_to_properties
      end

      def add_created_by
        header = po_header
        header['PO-RevisionDate'] = Time.now.strftime(PO_DATE_FORMAT)
        header['Last-Translator'] = 'Translatomatic ' + VERSION
      end

      def po_header
        # TODO: get or create header entry
        {}
      end

      # create mapping from key to PoProperty
      def init_pomap(po)
        po.entries.each_with_index do |entry, i|
          # skip PO file header if present
          # TODO: update PO-Revision-Date, Last-Provider ?
          next if entry.msgid == '' && i.zero?

          if entry.extracted_comment
            @metadata.parse_comment(entry.extracted_comment.value)
          end
          add_entry(entry, :msgid, 0)
          add_entry(entry, :msgid_plural, 1) if entry.plural?
          @metadata.clear_context
        end
      end

      def pomap_to_properties
        @pomap.transform_values { |i| i.value.to_s }
      end

      def add_entry(entry, key, msgstr_index)
        map_key = entry.send(key).to_s
        return unless map_key

        msg_context = entry.msgctxt
        map_key = map_key + '.' + msg_context.to_s if msg_context
        @pomap[map_key] = PoProperty.new(entry, msgstr_index)
        @metadata.assign_key(map_key, keep_context: true)
      end
    end
  end
end