From a25c64083c10dc2b2b02fcee06b1e305a379ce90 Mon Sep 17 00:00:00 2001
From: Ralph Amissah <ralph@amissah.com>
Date: Wed, 31 Dec 2014 08:50:09 -0500
Subject: d: po4a, continue reorganization (translation request dev stopped)

* --po4a run against different language versions of sisu markup
  files (representing the same document in different languages)
  initializes po4a structure to place those documents under future
  po4a management
* includes command line translation request
  (use command line program 'trans' to pass request to
  translation.google.com, stopped for now)
  NOTE in case future development is restarted: to test, remove
  code line 'auto_translate?(:skip)' that follows
  'def auto_translation(src_txt,markup=:src)'; place identical
  english sisu markup files in en/test.sst fr/test.sst (or under
  the language code to be tested) and run against en/test.sst
  fr/test.sst e.g. '--po4a --trans --glob test.sst'
  this send identical text objects to translate.google using
  'trans' and populate po file with results for placing future
  translation under po4a management, however in initial tests
  insufficient cleanly translated paragraphs were returned,
  so stopped development for now. (no attempt at initialization
  of new non-existent files using --trans-en:es,fr,de format)
* [hub_options, if development of trans is pursued later consider
  the possibility of modifying the --trans string options to add
  an optional timeout value, &; possibly modifying po4a code so
  timeout may occur a fixed number of times before skipping
  translation request attempts for the remainder].
---
 lib/sisu/develop/constants.rb    |  30 +-
 lib/sisu/develop/hub_options.rb  |  36 +-
 lib/sisu/develop/object_munge.rb | 307 +++++++++++++++++
 lib/sisu/develop/po4a.rb         | 712 ++++++++++++++++++---------------------
 lib/sisu/develop/po4a_set.rb     |   8 +-
 lib/sisu/develop/se_file_op.rb   |  11 +-
 6 files changed, 700 insertions(+), 404 deletions(-)
 create mode 100644 lib/sisu/develop/object_munge.rb

diff --git a/lib/sisu/develop/constants.rb b/lib/sisu/develop/constants.rb
index c5f439ca..8f108b75 100644
--- a/lib/sisu/develop/constants.rb
+++ b/lib/sisu/develop/constants.rb
@@ -147,6 +147,26 @@ Mx={
   sm_set_o:                  '◢',          sm_set_c:            '◣',
   sm_subset_o:               '◢',          sm_subset_c:         '◣',
   vline:                     '┆',                                              #  ¦ |
+  src_bold_o:                '!{',    src_bold_c:               '}!',
+  src_italics_o:             '/{',    src_italics_c:            '}/',
+  src_underscore_o:          '_{',    src_underscore_c:         '}_',
+  src_cite_o:                '"{',    src_cite_c:               '}"',
+  src_insert_o:              '+{',    src_insert_c:             '}+',
+  src_strike_o:              '-{',    src_strike_c:             '}-',
+  src_superscript_o:         '^{',    src_superscript_c:        '}^',
+  src_subscript_o:           ',{',    src_subscript_c:          '}',
+  src_hilite_o:              '*{',    src_hilite_c:             '}*',
+  src_monospace_o:           '#{',    src_monospace_c:          '}#',
+  srcrgx_bold_o:             '\!\{',   srcrgx_bold_c:           '\}\!',
+  srcrgx_italics_o:          '\/\{',   srcrgx_italics_c:        '\}\/',
+  srcrgx_underscore_o:       '_\{',    srcrgx_underscore_c:     '\}_',
+  srcrgx_cite_o:             '"\{',    srcrgx_cite_c:           '\}"',
+  srcrgx_insert_o:           '\+\{',   srcrgx_insert_c:         '\}\+',
+  srcrgx_strike_o:           '\-\{',   srcrgx_strike_c:         '\}\-',
+  srcrgx_superscript_o:      '\^\{',   srcrgx_superscript_c:    '\}\^',
+  srcrgx_subscript_o:        ',\{',    srcrgx_subscript_c:      '\},',
+  srcrgx_hilite_o:           '\*\{',   srcrgx_hilite_c:         '\}\*',
+  srcrgx_monospace_o:        '\#\{',   srcrgx_monospace_c:      '\}\#',
 }
 Mx[:fa_bold_o]=              "#{Mx[:fa_o]}b#{Mx[:fa_o_c]}"
 Mx[:fa_bold_c]=              "#{Mx[:fa_c_o]}b#{Mx[:fa_c]}"
@@ -221,16 +241,6 @@ Px={
   subscript_o:               '[',          subscript_c:              ']',
   hilite_o:                  '*',          hilite_c:                 '*',
   monospace_o:               '',           monospace_c:              '',
-  po_bold_o:                 '!{',         po_bold_c:                '}!',
-  po_italics_o:              '/{',         po_italics_c:             '}/',
-  po_underscore_o:           '_{',         po_underscore_c:          '}_',
-  po_cite_o:                 '"{',         po_cite_c:                '}"',
-  po_insert_o:               '+{',         po_insert_c:              '}+',
-  po_strike_o:               '-{',         po_strike_c:              '}-',
-  po_superscript_o:          '^{',         po_superscript_c:         '}^',
-  po_subscript_o:            ',{',         po_subscript_c:           '},',
-  po_hilite_o:               '*{',         po_hilite_c:              '}*',
-  po_monospace_o:            '#{',         po_monospace_c:           '}#',
   lng_lst:                   SiSU_is[:language_list],
   lng_lst_rgx:               SiSU_is[:language_list_regex],
   lv1:                       '*',
diff --git a/lib/sisu/develop/hub_options.rb b/lib/sisu/develop/hub_options.rb
index e7df01db..1ea96af8 100644
--- a/lib/sisu/develop/hub_options.rb
+++ b/lib/sisu/develop/hub_options.rb
@@ -1301,10 +1301,38 @@ module SiSU_Commandline
         =~/"--harvest"/) \
         ? { bool: true, set: :on }
         : { bool: false, set: :na }
-        act[:po4a]=(select_arr.inspect \
-        =~/"--po4a"|"--pot?"/) \
-        ? { bool: true, set: :on }
-        : { bool: false, set: :na }
+        act[:po4a]=if (select_arr.inspect \
+        =~/"--po4a"|"--pot?"/)
+          act[:po4a_lang_trans]=if select_arr.inspect \
+          =~/"--trans-([a-z]{2}):((?:(?:[a-z]{2}\b),?)+)/
+            lng_src,lng_trn=$1,$2.split(',')
+            { bool: true, set: :on, src: lng_src, trn: lng_trn }
+          elsif select_arr.inspect \
+          =~/"--trans"/
+            { bool: true, set: :on }
+            { bool: true, set: :on, src: 'en', trn: [] }
+          else
+            { bool: false, set: :na }
+          end
+          act[:po4a_lang_init]=if select_arr.inspect \
+          =~/"--init-([a-z]{2}):((?:(?:[a-z]{2}\b),?)+)/
+            lng_src,lng_trn=$1,$2.split(',')
+            { bool: true, set: :on, src: lng_src, trn: lng_trn }
+          else
+            { bool: false, set: :na }
+          end
+          { bool: true, set: :on }
+        else
+          act[:po4a_lang_trans]= \
+          { bool: false, set: :na }
+          act[:po4a_lang_init]= \
+          { bool: false, set: :na }
+          { bool: false, set: :na }
+        end
+        #act[:po4a]=(select_arr.inspect \
+        #=~/"--po4a"|"--pot?"/) \
+        #? { bool: true, set: :on }
+        #: { bool: false, set: :na }
         act[:git]=(select_arr.inspect \
         =~/"--git"/) \
         ? { bool: true, set: :on }
diff --git a/lib/sisu/develop/object_munge.rb b/lib/sisu/develop/object_munge.rb
new file mode 100644
index 00000000..0c2b5137
--- /dev/null
+++ b/lib/sisu/develop/object_munge.rb
@@ -0,0 +1,307 @@
+# encoding: utf-8
+=begin
+
+* Name: SiSU
+
+** Description: documents, structuring, processing, publishing, search
+*** object munge
+
+** Author: Ralph Amissah
+  <ralph@amissah.com>
+  <ralph.amissah@gmail.com>
+
+** Copyright: (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+  2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Ralph Amissah,
+  All Rights Reserved.
+
+** License: GPL 3 or later:
+
+  SiSU, a framework for document structuring, publishing and search
+
+  Copyright (C) Ralph Amissah
+
+  This program is free software: you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by the Free
+  Software Foundation, either version 3 of the License, or (at your option)
+  any later version.
+
+  This program is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+  more details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program. If not, see <http://www.gnu.org/licenses/>.
+
+  If you have Internet connection, the latest version of the GPL should be
+  available at these locations:
+  <http://www.fsf.org/licensing/licenses/gpl.html>
+  <http://www.gnu.org/licenses/gpl.html>
+
+  <http://www.sisudoc.org/sisu/en/manifest/gpl.fsf.html>
+
+** SiSU uses:
+  * Standard SiSU markup syntax,
+  * Standard SiSU meta-markup syntax, and the
+  * Standard SiSU object citation numbering and system
+
+** Hompages:
+  <http://www.jus.uio.no/sisu>
+  <http://www.sisudoc.org>
+
+** Git
+  <http://git.sisudoc.org/gitweb/?p=code/sisu.git;a=summary>
+  <http://git.sisudoc.org/gitweb/?p=code/sisu.git;a=blob;f=lib/sisu/develop/html_parts.rb;hb=HEAD>
+
+=end
+module SiSU_Object_Munge
+  def i_src_o_strip_markup(txtobj)
+    txtobj=txtobj.
+      gsub(/#{Mx[:srcrgx_bold_o]}(.+?)#{Mx[:srcrgx_bold_c]}/m,'\1').
+      gsub(/#{Mx[:srcrgx_italics_o]}(.+?)#{Mx[:srcrgx_italics_c]}/m,'\1').
+      gsub(/#{Mx[:srcrgx_underscore_o]}(.+?)#{Mx[:srcrgx_underscore_c]}/m,'\1').
+      gsub(/#{Mx[:srcrgx_cite_o]}(.+?)#{Mx[:srcrgx_cite_c]}/m,'\1').
+      gsub(/#{Mx[:srcrgx_insert_o]}(.+?)#{Mx[:srcrgx_insert_c]}/m,'\1').
+      gsub(/#{Mx[:srcrgx_strike_o]}(.+?)#{Mx[:srcrgx_strike_c]}/m,'\1').
+      gsub(/#{Mx[:srcrgx_superscript_o]}(\d+)#{Mx[:srcrgx_superscript_c]}/m,'[\1]').
+      gsub(/#{Mx[:srcrgx_superscript_o]}(.+?)#{Mx[:srcrgx_superscript_c]}/m,'\1').
+      gsub(/#{Mx[:srcrgx_subscript_o]}(.+?)#{Mx[:srcrgx_subscript_c]}/m,'\1').
+      gsub(/#{Mx[:srcrgx_hilite_o]}(.+?)#{Mx[:srcrgx_hilite_c]}/m,'\1').
+      gsub(/#{Mx[:gl_o]}#(?:126|152)#{Mx[:gl_c]}/i,'~').
+      gsub(/#{Mx[:en_a_o]}([\d*+]+)\s+(?:.+?)#{Mx[:en_a_c]}/m,''). # endnote removed
+      gsub(/#{Mx[:en_b_o]}([\d*+]+)\s+(?:.+?)#{Mx[:en_b_c]}/m,''). # endnote removed
+      gsub(/(?:#{Mx[:nbsp]})+/,' ').
+      gsub(/(?:#{Mx[:br_nl]})+/,"\n").
+      gsub(/(?:#{Mx[:br_paragraph]})+/,"\n").
+      gsub(/(?:#{Mx[:br_line]})+/,"\n").
+      gsub(/#{Mx[:gl_o]}(?:#lt|#060)#{Mx[:gl_c]}/,'<').
+      gsub(/#{Mx[:gl_o]}(?:#gt|#062)#{Mx[:gl_c]}/,'>').
+      gsub(/#{Mx[:gl_o]}#(?:038|amp)#{Mx[:gl_c]}/,'&').
+      gsub(/#{Mx[:gl_o]}#033#{Mx[:gl_c]}/,'!').
+      gsub(/#{Mx[:gl_o]}#035#{Mx[:gl_c]}/,'#').
+      gsub(/#{Mx[:gl_o]}#042#{Mx[:gl_c]}/,'*').
+      gsub(/#{Mx[:gl_o]}#045#{Mx[:gl_c]}/,'-').
+      gsub(/#{Mx[:gl_o]}#047#{Mx[:gl_c]}/,'/').
+      gsub(/#{Mx[:gl_o]}#095#{Mx[:gl_c]}/,'_').
+      gsub(/#{Mx[:gl_o]}#123#{Mx[:gl_c]}/,'{').
+      gsub(/#{Mx[:gl_o]}#125#{Mx[:gl_c]}/,'}').
+      gsub(/#{Mx[:gl_o]}#126#{Mx[:gl_c]}/,'~').
+      gsub(/#{Mx[:gl_o]}#169#{Mx[:gl_c]}/,'©').
+      gsub(/[ ][ ]s+/,' ').
+      strip
+if txtobj =~/Reading this/
+  puts txtobj
+  if txtobj =~ /#{Mx[:srcrgx_italics_o]}(.+?)#{Mx[:srcrgx_italics_c]}/
+    puts __LINE__
+    puts Mx[:srcrgx_italics_o]
+    puts txtobj
+  end
+end
+; txtobj
+  end
+  def i_ao_o_strip_markup(txtobj)
+    txtobj=txtobj.gsub(/#{Mx[:fa_bold_o]}(.+?)#{Mx[:fa_bold_c]}/,'\1').
+      gsub(/#{Mx[:fa_italics_o]}(.+?)#{Mx[:fa_italics_c]}/,'\1').
+      gsub(/#{Mx[:fa_underscore_o]}(.+?)#{Mx[:fa_underscore_c]}/,'\1').
+      gsub(/#{Mx[:fa_cite_o]}(.+?)#{Mx[:fa_cite_c]}/,'\1').
+      gsub(/#{Mx[:fa_insert_o]}(.+?)#{Mx[:fa_insert_c]}/,'\1').
+      gsub(/#{Mx[:fa_strike_o]}(.+?)#{Mx[:fa_strike_c]}/,'\1').
+      gsub(/#{Mx[:fa_superscript_o]}(\d+)#{Mx[:fa_superscript_c]}/,'[\1]').
+      gsub(/#{Mx[:fa_superscript_o]}(.+?)#{Mx[:fa_superscript_c]}/,'\1').
+      gsub(/#{Mx[:fa_subscript_o]}(.+?)#{Mx[:fa_subscript_c]}/,'\1').
+      gsub(/#{Mx[:fa_hilite_o]}(.+?)#{Mx[:fa_hilite_c]}/,'\1').
+      gsub(/#{Mx[:gl_o]}#(?:126|152)#{Mx[:gl_c]}/i,'~').
+      gsub(/#{Mx[:en_a_o]}([\d*+]+)\s+(?:.+?)#{Mx[:en_a_c]}/,''). # endnote removed
+      gsub(/#{Mx[:en_b_o]}([\d*+]+)\s+(?:.+?)#{Mx[:en_b_c]}/,''). # endnote removed
+      gsub(/(?:#{Mx[:nbsp]})+/,' ').
+      gsub(/(?:#{Mx[:br_nl]})+/,"\n").
+      gsub(/(?:#{Mx[:br_paragraph]})+/,"\n").
+      gsub(/(?:#{Mx[:br_line]})+/,"\n").
+      gsub(/#{Mx[:gl_o]}(?:#lt|#060)#{Mx[:gl_c]}/,'<').
+      gsub(/#{Mx[:gl_o]}(?:#gt|#062)#{Mx[:gl_c]}/,'>').
+      gsub(/#{Mx[:gl_o]}#(?:038|amp)#{Mx[:gl_c]}/,'&').
+      gsub(/#{Mx[:gl_o]}#033#{Mx[:gl_c]}/,'!').
+      gsub(/#{Mx[:gl_o]}#035#{Mx[:gl_c]}/,'#').
+      gsub(/#{Mx[:gl_o]}#042#{Mx[:gl_c]}/,'*').
+      gsub(/#{Mx[:gl_o]}#045#{Mx[:gl_c]}/,'-').
+      gsub(/#{Mx[:gl_o]}#047#{Mx[:gl_c]}/,'/').
+      gsub(/#{Mx[:gl_o]}#095#{Mx[:gl_c]}/,'_').
+      gsub(/#{Mx[:gl_o]}#123#{Mx[:gl_c]}/,'{').
+      gsub(/#{Mx[:gl_o]}#125#{Mx[:gl_c]}/,'}').
+      gsub(/#{Mx[:gl_o]}#126#{Mx[:gl_c]}/,'~').
+      gsub(/#{Mx[:gl_o]}#169#{Mx[:gl_c]}/,'©').
+      gsub(/[ ][ ]s+/,' ').
+      strip
+  end
+  def i_ao_o_src_markup_restore(txtobj)
+    @txtobj=txtobj
+    def textface_marks
+      @txtobj.gsub(/#{Mx[:fa_bold_o]}(.+?)#{Mx[:fa_bold_c]}/,'*{\1}*').
+        gsub(/#{Mx[:fa_italics_o]}(.+?)#{Mx[:fa_italics_c]}/,'/{\1}/').
+        gsub(/#{Mx[:fa_underscore_o]}(.+?)#{Mx[:fa_underscore_c]}/,'_{\1}_').
+        gsub(/#{Mx[:fa_cite_o]}(.+?)#{Mx[:fa_cite_c]}/,'"{\1}"').
+        gsub(/#{Mx[:fa_insert_o]}(.+?)#{Mx[:fa_insert_c]}/,'+{\1}+').
+        gsub(/#{Mx[:fa_strike_o]}(.+?)#{Mx[:fa_strike_c]}/,'-{\1}-').
+        gsub(/#{Mx[:fa_superscript_o]}(\d+)#{Mx[:fa_superscript_c]}/,'^{[\1]}^').
+        gsub(/#{Mx[:fa_superscript_o]}(.+?)#{Mx[:fa_superscript_c]}/,'^{\1}^').
+        gsub(/#{Mx[:fa_subscript_o]}(.+?)#{Mx[:fa_subscript_c]}/,',{\1},').
+        gsub(/#{Mx[:fa_hilite_o]}(.+?)#{Mx[:fa_hilite_c]}/,'\1').
+        gsub(/#{Mx[:gl_o]}#(?:126|152)#{Mx[:gl_c]}/i,'~').
+        gsub(/#{Mx[:en_a_o]}([\d*+]+)\s+(?:.+?)#{Mx[:en_a_c]}/,'~{\1 \2}~').
+        gsub(/#{Mx[:en_b_o]}([\d*+]+)\s+(?:.+?)#{Mx[:en_b_c]}/,''). # endnote removed
+        gsub(/(?:#{Mx[:nbsp]})+/,' ').
+        gsub(/(?:#{Mx[:br_nl]})+/,"\n").
+        gsub(/(?:#{Mx[:br_paragraph]})+/,"\n").
+        gsub(/(?:#{Mx[:br_line]})+/,"\n").
+        gsub(/#{Mx[:gl_o]}(?:#lt|#060)#{Mx[:gl_c]}/,'<').
+        gsub(/#{Mx[:gl_o]}(?:#gt|#062)#{Mx[:gl_c]}/,'>').
+        gsub(/#{Mx[:gl_o]}#(?:038|amp)#{Mx[:gl_c]}/,'&').
+        gsub(/#{Mx[:gl_o]}#033#{Mx[:gl_c]}/,'!').
+        gsub(/#{Mx[:gl_o]}#035#{Mx[:gl_c]}/,'#').
+        gsub(/#{Mx[:gl_o]}#042#{Mx[:gl_c]}/,'*').
+        gsub(/#{Mx[:gl_o]}#045#{Mx[:gl_c]}/,'-').
+        gsub(/#{Mx[:gl_o]}#047#{Mx[:gl_c]}/,'/').
+        gsub(/#{Mx[:gl_o]}#095#{Mx[:gl_c]}/,'_').
+        gsub(/#{Mx[:gl_o]}#123#{Mx[:gl_c]}/,'{').
+        gsub(/#{Mx[:gl_o]}#125#{Mx[:gl_c]}/,'}').
+        gsub(/#{Mx[:gl_o]}#126#{Mx[:gl_c]}/,'~').
+        gsub(/#{Mx[:gl_o]}#169#{Mx[:gl_c]}/,'©').
+        gsub(/[ ][ ]s+/,' ').
+        strip
+    end
+    def object_marks
+      @txtobj
+    end
+    self
+  end
+  def clean_text(txtobj,markup=:ao)
+    if txtobj.class==String
+      txtobj=if markup ==:ao
+        i_ao_o_strip_markup(txtobj)
+      elsif markup ==:src
+        i_src_o_strip_markup(txtobj)
+      else p __FILE__; p __LINE__
+      end
+    elsif txtobj.class.inspect=~/^SiSU_AO_DocumentStructure::/
+      txtobj.obj=i_ao_o_strip_markup(txtobj.obj)
+    else p 'error'
+    end
+    txtobj
+  end
+  def footnotes_inline(txtobj)
+  end
+  def footnotes_ref_and_note(txtobj)
+  end
+  def src_markup(txtobj)
+    txtobj
+  end
+  def extract_endnotes(doc_obj_txt,endnotes_)               #% used for extraction of endnotes from paragraphs
+    if endnotes_ ==:separate
+      notes_a=doc_obj_txt.scan(/#{Mx[:en_a_o]}([\d]+\s+.+?)#{Mx[:en_a_c]}/)
+      ##notes_a=doc_obj_txt.scan(/#{Mx[:en_a_o]}([\d*+]+\s+.+?)#{Mx[:en_a_c]}/)
+      #notes_b=doc_obj_txt.scan(/#{Mx[:en_b_o]}([\d*+]+\s+.+?)#{Mx[:en_b_c]}/)
+      n=[]
+      notes_a.flatten.each do |note| #high cost to deal with <br> appropriately within plaintext, consider
+        note=note.dup.to_s
+        note=note.gsub(/^([\d]+)\s+/,'^~\1 ').
+          gsub(/#{Mx[:br_line]}|#{Mx[:br_nl]}/,
+            ' \\\\\\ ')
+        n << note
+      end
+      notes_a=n.flatten
+      doc_obj_txt=doc_obj_txt.
+        gsub(/#{Mx[:en_a_o]}([\d]+)\s+(?:.+?)#{Mx[:en_a_c]}/,'~^')   # endnote marker marked up
+    else
+      doc_obj_txt=doc_obj_txt.
+        gsub(/#{Mx[:en_b_o]}[\d]+\s+(.+?)#{Mx[:en_b_c]}/,
+          '~[ \1 ]~').     # inline endnote with marker marked up
+        gsub(/#{Mx[:en_a_o]}([*+]+)\s+(.+?)#{Mx[:en_a_c]}/,
+          '~{\1 \2 }~'). # inline endnote with marker marked up
+        gsub(/#{Mx[:en_b_o]}([*+]+)\s+(.+?)#{Mx[:en_b_c]}/,
+          '~[\1 \2 ]~') # inline endnote with marker marked up
+    end
+    [doc_obj_txt,notes_a]
+  end
+  def objects #def i_ao_o_src_markup_restore(txtobj)
+    def code_(dob)
+      if dob.is==:code
+        dob.obj=dob.obj.gsub(/(^|[^}])_([<>])/m,'\1\2'). # _> _<
+          gsub(/(^|[^}])_([<>])/m,'\1\2') # _<_<
+      end
+      dob
+    end
+    def block_(dob)
+      dob.obj=if dob.of==:block                                   # watch
+        dob.obj.gsub(/#{Mx[:gl_o]}●#{Mx[:gl_c]}/,"* ").
+          gsub(/#{Mx[:br_line]}|#{Mx[:br_nl]}/,"\n")
+      else dob.obj.gsub(/#{Mx[:br_line]}|#{Mx[:br_nl]}/,"\n\n")
+      end
+      dob
+    end
+    def textface_marks_po4a(dob,endnotes_=:inline)
+      notes=''
+      dob.obj=dob.obj.
+        gsub(/#{Mx[:fa_bold_o]}(.+?)#{Mx[:fa_bold_c]}/,
+          Mx[:src_bold_o] + '\1' + Mx[:src_bold_c]).
+        gsub(/#{Mx[:fa_italics_o]}(.+?)#{Mx[:fa_italics_c]}/,
+          Mx[:src_italics_o] + '\1' + Mx[:src_italics_c]).
+        gsub(/#{Mx[:fa_underscore_o]}(.+?)#{Mx[:fa_underscore_c]}/,
+          Mx[:src_underscore_o] + '\1' + Mx[:src_underscore_c]).
+        gsub(/#{Mx[:fa_subscript_o]}(.+?)#{Mx[:fa_subscript_c]}/,
+          Mx[:src_subscript_o] + '\1' + Mx[:src_subscript_c]).
+        gsub(/#{Mx[:fa_superscript_o]}(.+?)#{Mx[:fa_superscript_c]}/,
+          Mx[:src_superscript_o] + '\1' + Mx[:src_superscript_c]).
+        gsub(/#{Mx[:fa_insert_o]}(.+?)#{Mx[:fa_insert_c]}/,
+          Mx[:src_insert_o] + '\1' + Mx[:src_insert_c]).
+        gsub(/#{Mx[:fa_cite_o]}(.+?)#{Mx[:fa_cite_c]}/,
+          Mx[:src_cite_o] + '\1' + Mx[:src_cite_c]).
+        gsub(/#{Mx[:fa_strike_o]}(.+?)#{Mx[:fa_strike_c]}/,
+          Mx[:src_strike_o] + '\1' + Mx[:src_strike_c]).
+        gsub(/#{Mx[:fa_monospace_o]}(.+?)#{Mx[:fa_monospace_c]}/,
+          Mx[:src_monospace_o] + '\1' + Mx[:src_monospace_c])
+      unless dob.is==:code
+        dob.obj=dob.obj.
+          gsub(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}#{Mx[:rel_o]}\S+?#{Mx[:rel_c]}/,'\1').
+          gsub(/#{Mx[:url_o]}_(\S+?)#{Mx[:url_c]}/,'\1').
+          gsub(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/,
+            '\1 [link: <\2>]').
+          gsub(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}image/,
+            '\1 [link: local image]').
+          gsub(/#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/,'\1')
+        dob.obj,notes=extract_endnotes(dob.obj,endnotes_)
+        dob.obj=dob.obj.
+          gsub(/#{Mx[:gl_o]}(?:#lt|#060)#{Mx[:gl_c]}/,'<').
+          gsub(/#{Mx[:gl_o]}(?:#gt|#062)#{Mx[:gl_c]}/,'>').
+          gsub(/#{Mx[:gl_o]}#(?:038|amp)#{Mx[:gl_c]}/,'&').
+          gsub(/#{Mx[:gl_o]}#033#{Mx[:gl_c]}/,'!').
+          gsub(/#{Mx[:gl_o]}#035#{Mx[:gl_c]}/,'#').
+          gsub(/#{Mx[:gl_o]}#042#{Mx[:gl_c]}/,'*').
+          gsub(/#{Mx[:gl_o]}#045#{Mx[:gl_c]}/,'-').
+          gsub(/#{Mx[:gl_o]}#047#{Mx[:gl_c]}/,'/').
+          gsub(/#{Mx[:gl_o]}#095#{Mx[:gl_c]}/,'_').
+          gsub(/#{Mx[:gl_o]}#123#{Mx[:gl_c]}/,'{').
+          gsub(/#{Mx[:gl_o]}#125#{Mx[:gl_c]}/,'}').
+          gsub(/#{Mx[:gl_o]}#126#{Mx[:gl_c]}/,'~').
+          gsub(/#{Mx[:gl_o]}#169#{Mx[:gl_c]}/,'©')
+      end
+      dob=block_(dob)
+      dob=code_(dob)
+      dob.obj=dob.obj.gsub(/#{Mx[:br_page]}\s*|#{Mx[:br_page_new]}/,''). # remove page breaks
+        gsub(/#{Mx[:url_o]}_(\S+?)#{Mx[:url_c]}/,'\1').
+        gsub(/#{Mx[:mk_o]}:name#(\S+?)#{Mx[:mk_c]}/,'').                 # remove name links
+        gsub(/&nbsp;|#{Mx[:nbsp]}/,' ').                                 # decide on
+        gsub(/(?:^|[^_\\])#{Mx[:lnk_o]}(\S+?\.(?:png|jpg|gif)) .+?#{Mx[:lnk_c]}#{Mx[:url_o]}\S+?#{Mx[:url_c]}/,
+          '    [ \1 ]'). #"[ #{dir.url.images_local}\/\\1 ]")
+        gsub(/(?:^|[^_\\])#{Mx[:lnk_o]}(\S+?\.(?:png|jpg|gif)) .+?#{Mx[:lnk_c]}image/,
+          '    [ \1 ]'). #"[ #{dir.url.images_local}\/\\1 ]")
+        gsub(/(?:^|[^_\\])\{\s*\S+?\.(?:png|jpg|gif)\s+.+?"(.*?)"\s*\}\S+/,
+          '[image: "\1"]')
+      [dob,notes]
+    end
+    def object_marks
+      @txtobj
+    end
+    self
+  end
+end
+__END__
diff --git a/lib/sisu/develop/po4a.rb b/lib/sisu/develop/po4a.rb
index 4b41f1da..5cc36886 100644
--- a/lib/sisu/develop/po4a.rb
+++ b/lib/sisu/develop/po4a.rb
@@ -62,7 +62,9 @@ module SiSU_Po4a
   require_relative 'shared_metadata'                    # shared_metadata.rb
   require_relative 'po4a_set'                           # po4a_set.rb
   include SiSU_Param
+  require_relative 'object_munge'                       # object_munge.rb
   class Source
+    include SiSU_Object_Munge
     @@opt_src,@@opt_trn,@@opt_src_,@@opt_trn_,@@md_src,@@md_trn=
           nil,      nil,       nil,       nil,     nil,     nil
     @@auto_translation_ = :go
@@ -210,7 +212,9 @@ module SiSU_Po4a
         ? md_src
         : md_trn
         @tab="\t"
-        @@endnotes_=(@md.opt.selections.str =~/--endnote/) ? true : false    # --footnote
+        @@endnotes_=(@md.opt.selections.str =~/--endnote/) \
+        ? true
+        : false    # --footnote
         @pot={
           body: [],
           open: [],
@@ -224,24 +228,20 @@ module SiSU_Po4a
         (@md.opt.selections.str =~/--dos/) ? "\r\n" : "\n"  # --unix
       end
       def songsheet
-############## BUG @fn changes value
         fn=@fn
         pot=pot_markup(@data_src,@data_trn)
         publish(fn,pot)
       end
-      def extract_endnotes(dob='')               #% used for extraction of endnotes from paragraphs
-        notes_a=dob.obj.scan(/#{Mx[:en_a_o]}([\d]+\s+.+?)#{Mx[:en_a_c]}/)
-        ##notes_a=dob.obj.scan(/#{Mx[:en_a_o]}([\d*+]+\s+.+?)#{Mx[:en_a_c]}/)
-        #notes_b=dob.obj.scan(/#{Mx[:en_b_o]}([\d*+]+\s+.+?)#{Mx[:en_b_c]}/)
-        @n=[]
-        notes_a.flatten.each do |n| #high cost to deal with <br> appropriately within plaintext, consider
-          n=n.dup.to_s
-          n=n.gsub(/^([\d]+)\s+/,'^~\1 ').
-            gsub(/#{Mx[:br_line]}|#{Mx[:br_nl]}/,
-              ' \\\\\\ ')
-          @n << n
-        end
-        notes_a=@n.flatten
+      def pot_structure_wrap(desc,orig,trans,indent=0,hang=0)
+        SiSU_Po4aUtils::Wrap.new(
+          @md,
+          orig,
+          trans,
+          desc,
+          @wrap_width,
+          indent,
+          hang
+        )
       end
       def wrap_endnotes(orig_notes='',trn_notes='')
         nt=@@endnotes_ ? 'endnote' : 'footnote'
@@ -273,7 +273,7 @@ module SiSU_Po4a
             : trn_notes[i].to_s
           else ''
           end
-          util=pot_structure(desc,orig,trans)
+          util=pot_structure_wrap(desc,orig,trans)
           wrap=util.line_wrap
           wrap=if wrap =~ /^\s*\^~[\d*+]+\s+.+?\s*\Z/m
             wrap.gsub(/^\s*(\^~[\d*+]+)\s+(.+?)\s*\Z/m, <<GSUB
@@ -548,29 +548,31 @@ GSUB
           #puts z unless z.empty?
         end
       end
-      def pot_structure(desc,orig,trans,indent=0,hang=0)
-        SiSU_Po4aUtils::Wrap.new(
-          @md,
-          orig,
-          trans,
-          desc,
-          @wrap_width,
-          indent,
-          hang
-        )
-      end
-      def auto_translate?(set=nil)
-        @@auto_translation_=set \
-        ? set
-        : @@auto_translation_
+      def auto_translate?(set_to=nil)
+        @@auto_translation_=
+        if @md.opt.act[:po4a_lang_trans][:set]==:on
+          set_to \
+          ? set_to
+          : @@auto_translation_
+        else :skip
+        end
       end
-      def auto_translation(src_txt) # check for an appropriate request flag
+      def auto_translation(src_txt,markup=:src) # check for an appropriate request flag
+        auto_translate?(:skip)
         begin
+          src_txt_clean=clean_text(src_txt,markup)
+          src_txt_clean=src_txt_clean.
+            gsub(/\n/,' ').
+            gsub(/"/,'\"').
+            gsub(/([()])/,'\\\\\1')
           trans=''
           unless auto_translate? == :skip
             require 'timeout'
-            Timeout::timeout(5) {
-              #trans=`trans en:#{@md.opt.f_pth[:lng]} #{src_txt}` #+ ' ,{[G.Tr]},'
+            Timeout::timeout(60) {
+              trans=`trans -b -no-ansi en:#{@md.opt.f_pth[:lng_is]} #{src_txt_clean}`.strip
+              unless trans.empty?
+                trans + ' {[G.Tr]}http://translate.google.com'
+              end
             }
           end
           trans
@@ -579,91 +581,21 @@ GSUB
           p 'timeout issues with translation, skip remaining'
         end
       end
-      def pot_structure_heading(dob_src='',notes_s='',dob_trn='',notes_t='')   #% used to extract the structure of a document
-        lv=n=n3=nil
-        lv=dob_src.ln
-        n=lv - 1
-        n3=lv + 2
-        util=nil
-        fn=(dob_src.name=~/[a-z\d]/i) ? dob_src.name : ''
-        mark="#{dob_src.lv}~#{fn} "
-        d="#{dob_src.is.to_s} (level #{dob_src.lv})"
-        instruct=s_mark=''
-        if @md.opt.act[:maintenance][:set]==:on
-          instruct=%{\n# markup for headings is marker at the start of the line/object, } \
-          + %{indicating the heading level, and if provided an associated name tag, } \
-          + %{this heading is "#{mark}"}
-          s_mark="\n# " + %{"\\n\\n#{mark}...\\n\\n"}
-        end
-        desc="#{d}#{s_mark}#{instruct}"
-        orig="#{s_mark}#{dob_src.obj}"
-        trans=((dob_trn=='') \
-        || (dob_src.obj == dob_trn.obj)) \
-        ? ''
-        : "#{s_mark}#{dob_trn.obj}"
-        if trans.empty? # and --auto-trans
-          trans=auto_translation(dob_src.obj)
-        end
-        util=pot_structure(desc,orig,trans)
-        wrapped=util.line_wrap
-        @pot[:body] << wrapped << br # main text, contents, body KEEP
-        if @@endnotes[:para] \
-        and notes_s.length > 0 \
-        and not @@endnotes_
-          @pot[:body] << br
-          wrap_endnotes(notes_s,notes_t)
-        elsif @@endnotes[:para] \
-        and @@endnotes_
-          @pot[:body] << br*2
-        end
-      end
-      def pot_structure_para(dob_src='',notes_s='',dob_trn='',notes_t='')      #% used to extract the structure of a document
-        util=nil
-        wrapped=if dob_src.indent =~/[1-9]/ \
-        and dob_src.indent == dob_src.hang
-          s_mark=desc=orig=trans=''
-          if dob_src.bullet_
-            mark="_#{dob_src.indent}* "
-            d="#{dob_src.is.to_s}: indent #{dob_src.indent}, bullet"
-            instruct=s_mark=''
-            if @md.opt.act[:maintenance][:set]==:on
-              instruct=%{\n# markup for indented bullet text is at the start of the line/object, } \
-              + %{an underscore followed by the indent level and an asterisk "#{mark}"}
-              s_mark="\n# " + %{"\\n\\n#{mark}...\\n\\n"}
-            end
-            desc="#{d}#{s_mark}#{instruct}"
-          else
-            mark="_#{dob_src.indent} "
-            d="#{dob_src.is.to_s}: indent #{dob_src.indent}"
-            instruct=s_mark=''
-            if @md.opt.act[:maintenance][:set]==:on
-              instruct=%{\n# markup for indented text is at the start of the line/object, } \
-              + %{an underscore followed by the indent level "#{mark}"}
-              s_mark="\n# " + %{"\\n\\n#{mark}...\\n\\n"}
-            end
-            desc="#{d}#{s_mark}#{instruct}"
-          end
-          orig="#{s_mark}#{dob_src.obj}"
-          trans=((dob_trn=='') \
-          || (dob_src.obj == dob_trn.obj)) \
-          ? ''
-          : "#{s_mark}#{dob_trn.obj}"
-          if trans.empty? # and --auto-trans
-            trans=auto_translation(dob_src.obj)
-          end
-          util=pot_structure(desc,orig,trans)
-        elsif dob_src.hang =~/[0-9]/ \
-        and dob_src.indent != dob_src.hang
-          s_mark=desc=orig=trans=''
-          mark="_#{dob_src.hang}_#{dob_src.indent} "
-          d="#{dob_src.is.to_s}: hang #{dob_src.hang} indent #{dob_src.indent}"
+      def pot_structure
+        def heading(dob_src='',notes_s='',dob_trn='',notes_t='')   #% used to extract the structure of a document
+          lv=n=n3=nil
+          lv=dob_src.ln
+          n=lv - 1
+          n3=lv + 2
+          util=nil
+          fn=(dob_src.name=~/[a-z\d]/i) ? dob_src.name : ''
+          mark="#{dob_src.lv}~#{fn} "
+          d="#{dob_src.is.to_s} (level #{dob_src.lv})"
           instruct=s_mark=''
           if @md.opt.act[:maintenance][:set]==:on
-            instruct=%{\n# markup for indented text with a first line indented } \
-            + %{to a different level from the rest of the paragraph, } \
-            + %{is at the start of the line/object, } \
-            + %{an underscore and the first indent level } \
-            + %{a second underscore and the indent level for the rest of the paragraph, "#{mark1}"}
+            instruct=%{\n# markup for headings is marker at the start of the line/object, } \
+            + %{indicating the heading level, and if provided an associated name tag, } \
+            + %{this heading is "#{mark}"}
             s_mark="\n# " + %{"\\n\\n#{mark}...\\n\\n"}
           end
           desc="#{d}#{s_mark}#{instruct}"
@@ -672,185 +604,271 @@ GSUB
           || (dob_src.obj == dob_trn.obj)) \
           ? ''
           : "#{s_mark}#{dob_trn.obj}"
-          if trans.empty? # and --auto-trans
-            trans=auto_translation(dob_src.obj)
+          if @md.opt.f_pth[:lng_is] !=@md.opt.lng_base \
+          and trans.empty? \
+          and auto_translate?
+            trans=auto_translation(dob_src.obj,:src)
           end
-          util=pot_structure(desc,orig,trans)
-        else
-          s_mark=desc=orig=trans=''
-          if dob_src.bullet_
-            mark='_* '
-            d="#{dob_src.is.to_s}: bullet"
-            instruct=s_mark=''
-            if @md.opt.act[:maintenance][:set]==:on
-              instruct=%{\n# markup for indented text is at the start of the line/object, } \
-              + %{an underscore followed by an asterisk "#{mark}"}
-              s_mark="\n# " + %{"\\n\\n#{mark}...\\n\\n"}
+          util=pot_structure_wrap(desc,orig,trans)
+          wrapped=util.line_wrap
+          @pot[:body] << wrapped << br # main text, contents, body KEEP
+          if @@endnotes[:para] \
+          and notes_s.length > 0 \
+          and not @@endnotes_
+            @pot[:body] << br
+            wrap_endnotes(notes_s,notes_t)
+          elsif @@endnotes[:para] \
+          and @@endnotes_
+            @pot[:body] << br*2
+          end
+        end
+        def para(dob_src='',notes_s='',dob_trn='',notes_t='')      #% used to extract the structure of a document
+          util=nil
+          wrapped=if dob_src.indent =~/[1-9]/ \
+          and dob_src.indent == dob_src.hang
+            s_mark=desc=orig=trans=''
+            if dob_src.bullet_
+              mark="_#{dob_src.indent}* "
+              d="#{dob_src.is.to_s}: indent #{dob_src.indent}, bullet"
+              instruct=s_mark=''
+              if @md.opt.act[:maintenance][:set]==:on
+                instruct=%{\n# markup for indented bullet text is at the start of the line/object, } \
+                + %{an underscore followed by the indent level and an asterisk "#{mark}"}
+                s_mark="\n# " + %{"\\n\\n#{mark}...\\n\\n"}
+              end
+              desc="#{d}#{s_mark}#{instruct}"
+            else
+              mark="_#{dob_src.indent} "
+              d="#{dob_src.is.to_s}: indent #{dob_src.indent}"
+              instruct=s_mark=''
+              if @md.opt.act[:maintenance][:set]==:on
+                instruct=%{\n# markup for indented text is at the start of the line/object, } \
+                + %{an underscore followed by the indent level "#{mark}"}
+                s_mark="\n# " + %{"\\n\\n#{mark}...\\n\\n"}
+              end
+              desc="#{d}#{s_mark}#{instruct}"
             end
-            desc="#{d}#{s_mark}#{instruct}"
             orig="#{s_mark}#{dob_src.obj}"
             trans=((dob_trn=='') \
             || (dob_src.obj == dob_trn.obj)) \
             ? ''
             : "#{s_mark}#{dob_trn.obj}"
-            if trans.empty? # and --auto-trans
-              trans=auto_translation(dob_src.obj)
+            if @md.opt.f_pth[:lng_is] !=@md.opt.lng_base \
+            and trans.empty? \
+            and auto_translate?
+              trans=auto_translation(dob_src.obj,:src)
             end
-          else
-            mark=''
-            d=dob_src.is.to_s
-            instruct=%{\n# regular paragraph, no special markup}
+            util=pot_structure_wrap(desc,orig,trans)
+          elsif dob_src.hang =~/[0-9]/ \
+          and dob_src.indent != dob_src.hang
+            s_mark=desc=orig=trans=''
+            mark="_#{dob_src.hang}_#{dob_src.indent} "
+            d="#{dob_src.is.to_s}: hang #{dob_src.hang} indent #{dob_src.indent}"
+            instruct=s_mark=''
             if @md.opt.act[:maintenance][:set]==:on
-              instruct="\n# "
+              instruct=%{\n# markup for indented text with a first line indented } \
+              + %{to a different level from the rest of the paragraph, } \
+              + %{is at the start of the line/object, } \
+              + %{an underscore and the first indent level } \
+              + %{a second underscore and the indent level for the rest of the paragraph, "#{mark1}"}
               s_mark="\n# " + %{"\\n\\n#{mark}...\\n\\n"}
             end
             desc="#{d}#{s_mark}#{instruct}"
-            orig=dob_src.obj
+            orig="#{s_mark}#{dob_src.obj}"
             trans=((dob_trn=='') \
             || (dob_src.obj == dob_trn.obj)) \
             ? ''
             : "#{s_mark}#{dob_trn.obj}"
-            if trans.empty? # and --auto-trans
-              trans=auto_translation(dob_src.obj)
+            if @md.opt.f_pth[:lng_is] !=@md.opt.lng_base \
+            and trans.empty? \
+            and auto_translate?
+              trans=auto_translation(dob_src.obj,:src)
             end
+            util=pot_structure_wrap(desc,orig,trans)
+          else
+            s_mark=desc=orig=trans=''
+            if dob_src.bullet_
+              mark='_* '
+              d="#{dob_src.is.to_s}: bullet"
+              instruct=s_mark=''
+              if @md.opt.act[:maintenance][:set]==:on
+                instruct=%{\n# markup for indented text is at the start of the line/object, } \
+                + %{an underscore followed by an asterisk "#{mark}"}
+                s_mark="\n# " + %{"\\n\\n#{mark}...\\n\\n"}
+              end
+              desc="#{d}#{s_mark}#{instruct}"
+              orig="#{s_mark}#{dob_src.obj}"
+              trans=((dob_trn=='') \
+              || (dob_src.obj == dob_trn.obj)) \
+              ? ''
+              : "#{s_mark}#{dob_trn.obj}"
+              if @md.opt.f_pth[:lng_is] !=@md.opt.lng_base \
+              and trans.empty? \
+              and auto_translate?
+                trans=auto_translation(dob_src.obj,:src)
+              end
+            else
+              mark=''
+              d=dob_src.is.to_s
+              instruct=%{\n# regular paragraph, no special markup}
+              if @md.opt.act[:maintenance][:set]==:on
+                instruct="\n# "
+                s_mark="\n# " + %{"\\n\\n#{mark}...\\n\\n"}
+              end
+              desc="#{d}#{s_mark}#{instruct}"
+              orig=dob_src.obj
+              trans=((dob_trn=='') \
+              || (dob_src.obj == dob_trn.obj)) \
+              ? ''
+              : "#{s_mark}#{dob_trn.obj}"
+              if @md.opt.f_pth[:lng_is] !=@md.opt.lng_base \
+              and trans.empty? \
+              and auto_translate?
+                trans=auto_translation(dob_src.obj,:src)
+              end
+            end
+            util=pot_structure_wrap(desc,orig,trans)
+          end
+          wrapped=util.line_wrap
+          @pot[:body] << wrapped << br # main text, contents, body KEEP
+          if @@endnotes[:para] \
+          and notes_s.length > 0 \
+          and not @@endnotes_
+            @pot[:body] << br
+            wrap_endnotes(notes_s,notes_t)
+          elsif @@endnotes[:para] \
+          and @@endnotes_
+            @pot[:body] << br*2
           end
-          util=pot_structure(desc,orig,trans)
-        end
-        wrapped=util.line_wrap
-        @pot[:body] << wrapped << br # main text, contents, body KEEP
-        if @@endnotes[:para] \
-        and notes_s.length > 0 \
-        and not @@endnotes_
-          @pot[:body] << br
-          wrap_endnotes(notes_s,notes_t)
-        elsif @@endnotes[:para] \
-        and @@endnotes_
-          @pot[:body] << br*2
-        end
-      end
-      def pot_structure_block(dob_src='',notes_s='',dob_trn='',notes_t='')     #% used to extract the structure of a document
-        mark="block{\\n\\n...\\n\\n}block"
-        d=dob_src.is.to_s
-        instruct=s_mark=''
-        if @md.opt.act[:maintenance][:set]==:on
-          instruct=%{\n# block text is a text block with an opening and closing marker, } \
-          + %{the content of which may be wrapped}
-          s_mark="\n# " + %{"\\n\\n#{mark}\\n\\n"}
-        end
-        desc="#{d}#{s_mark}#{instruct}"
-        orig=dob_src.obj
-        trans=((dob_trn=='') \
-        || (dob_src.obj == dob_trn.obj)) \
-        ? ''
-        : "#{s_mark}#{dob_trn.obj}"
-        if trans.empty? # and --auto-trans
-          trans=auto_translation(dob_src.obj)
         end
-        util=pot_structure(desc,orig,trans)
-        unwrapped=util.no_line_wrap_block
-        @pot[:body] << unwrapped << br
-      end
-      def pot_structure_group(dob_src='',notes_s='',dob_trn='',notes_t='')     #% used to extract the structure of a document
-        mark="group{\\n\\n...\\n\\n}group"
-        d=dob_src.is.to_s
-        instruct=s_mark=''
-        if @md.opt.act[:maintenance][:set]==:on
-          instruct=%{\n# group text is a text block with an opening and closing marker, } \
-          + %{the content of which may be wrapped}
-          s_mark="\n# " + %{"\\n\\n#{mark}\\n\\n"}
+        def block(dob_src='',notes_s='',dob_trn='',notes_t='')     #% used to extract the structure of a document
+          mark="block{\\n\\n...\\n\\n}block"
+          d=dob_src.is.to_s
+          instruct=s_mark=''
+          if @md.opt.act[:maintenance][:set]==:on
+            instruct=%{\n# block text is a text block with an opening and closing marker, } \
+            + %{the content of which may be wrapped}
+            s_mark="\n# " + %{"\\n\\n#{mark}\\n\\n"}
+          end
+          desc="#{d}#{s_mark}#{instruct}"
+          orig=dob_src.obj
+          trans=((dob_trn=='') \
+          || (dob_src.obj == dob_trn.obj)) \
+          ? ''
+          : "#{s_mark}#{dob_trn.obj}"
+          if @md.opt.f_pth[:lng_is] !=@md.opt.lng_base \
+          and trans.empty? \
+          and auto_translate?
+            trans=auto_translation(dob_src.obj,:src)
+          end
+          util=pot_structure_wrap(desc,orig,trans)
+          unwrapped=util.no_line_wrap_block
+          @pot[:body] << unwrapped << br
         end
-        desc="#{d}#{s_mark}#{instruct}"
-        orig=dob_src.obj
-        trans=((dob_trn=='') \
-        || (dob_src.obj == dob_trn.obj)) \
-        ? ''
-        : "#{s_mark}#{dob_trn.obj}"
-        if trans.empty? # and --auto-trans
-          trans=auto_translation(dob_src.obj)
+        def group(dob_src='',notes_s='',dob_trn='',notes_t='')     #% used to extract the structure of a document
+          mark="group{\\n\\n...\\n\\n}group"
+          d=dob_src.is.to_s
+          instruct=s_mark=''
+          if @md.opt.act[:maintenance][:set]==:on
+            instruct=%{\n# group text is a text block with an opening and closing marker, } \
+            + %{the content of which may be wrapped}
+            s_mark="\n# " + %{"\\n\\n#{mark}\\n\\n"}
+          end
+          desc="#{d}#{s_mark}#{instruct}"
+          orig=dob_src.obj
+          trans=((dob_trn=='') \
+          || (dob_src.obj == dob_trn.obj)) \
+          ? ''
+          : "#{s_mark}#{dob_trn.obj}"
+          if @md.opt.f_pth[:lng_is] !=@md.opt.lng_base \
+          and trans.empty? \
+          and auto_translate?
+            trans=auto_translation(dob_src.obj,:src)
+          end
+          util=pot_structure_wrap(desc,orig,trans)
+          unwrapped=util.no_line_wrap_block
+          @pot[:body] << unwrapped << br
         end
-        util=pot_structure(desc,orig,trans)
-        unwrapped=util.no_line_wrap_block
-        @pot[:body] << unwrapped << br
-      end
-      def pot_structure_verse(dob_src='',notes_s='',dob_trn='',notes_t='')     #% used to extract the structure of a document
-        mark="poem{\n\nverse\n\nverse\n\n...\n\n}poem"
-        d=dob_src.is.to_s
-        instruct=s_mark=''
-        if @md.opt.act[:maintenance][:set]==:on
-          instruct=%{\n# verse are part of the text block described as a poem, } \
-          + %{the first verse is preceeded by an opening marker, } \
-          + %{and the last verse by a closing marker, } \
-          + %{the content of which should remain unwrapped}
-          s_mark="\n# " + %{"\\n\\n#{mark}\\n\\n"}
+        def verse(dob_src='',notes_s='',dob_trn='',notes_t='')     #% used to extract the structure of a document
+          mark="poem{\n\nverse\n\nverse\n\n...\n\n}poem"
+          d=dob_src.is.to_s
+          instruct=s_mark=''
+          if @md.opt.act[:maintenance][:set]==:on
+            instruct=%{\n# verse are part of the text block described as a poem, } \
+            + %{the first verse is preceeded by an opening marker, } \
+            + %{and the last verse by a closing marker, } \
+            + %{the content of which should remain unwrapped}
+            s_mark="\n# " + %{"\\n\\n#{mark}\\n\\n"}
+          end
+          desc="#{d}#{s_mark}#{instruct}"
+          orig=dob_src.obj
+          trans=(dob_trn=='') ? '' : dob_trn.obj
+          util=pot_structure_wrap(desc,orig,trans)
+          unwrapped=util.no_line_wrap_block
+          @pot[:body] << unwrapped << br
         end
-        desc="#{d}#{s_mark}#{instruct}"
-        orig=dob_src.obj
-        trans=(dob_trn=='') ? '' : dob_trn.obj
-        util=pot_structure(desc,orig,trans)
-        unwrapped=util.no_line_wrap_block
-        @pot[:body] << unwrapped << br
-      end
-      def pot_structure_code(dob_src='',notes_s='',dob_trn='',notes_t='')      #% used to extract the structure of a document
-        mark="code{\\n\\n...\\n\\n}code"
-        d=dob_src.is.to_s
-        instruct=s_mark=''
-        if @md.opt.act[:maintenance][:set]==:on
-          instruct=%{\n# codeblocks are a text block with an opening and closing marker, } \
-          + %{the content of which should remain unwrapped}
-          s_mark="\n# " + %{"\\n\\n#{mark}\\n\\n"}
+        def code(dob_src='',notes_s='',dob_trn='',notes_t='')      #% used to extract the structure of a document
+          mark="code{\\n\\n...\\n\\n}code"
+          d=dob_src.is.to_s
+          instruct=s_mark=''
+          if @md.opt.act[:maintenance][:set]==:on
+            instruct=%{\n# codeblocks are a text block with an opening and closing marker, } \
+            + %{the content of which should remain unwrapped}
+            s_mark="\n# " + %{"\\n\\n#{mark}\\n\\n"}
+          end
+          desc="#{d}#{s_mark}#{instruct}"
+          orig=dob_src.obj
+          trans=(dob_trn=='') ? '' : dob_trn.obj
+          util=pot_structure_wrap(desc,orig,trans)
+          unwrapped=util.no_line_wrap_block
+          @pot[:body] << unwrapped << br
         end
-        desc="#{d}#{s_mark}#{instruct}"
-        orig=dob_src.obj
-        trans=(dob_trn=='') ? '' : dob_trn.obj
-        util=pot_structure(desc,orig,trans)
-        unwrapped=util.no_line_wrap_block
-        @pot[:body] << unwrapped << br
-      end
-      def pot_structure_table(dob_src='',notes_s='',dob_trn='',notes_t='')     #% used to extract the structure of a document
-        mark="table{\\n\\n...\\n\\n}table"
-        d=dob_src.is.to_s
-        instruct=s_mark=''
-        if @md.opt.act[:maintenance][:set]==:on
-          instruct=%{\n# tables are a text block with an opening and closing marker, } \
-          + %{the content of which should remain unwrapped}
-          s_mark="\n# " + %{"\\n\\n#{mark}\\n\\n"}
+        def table(dob_src='',notes_s='',dob_trn='',notes_t='')     #% used to extract the structure of a document
+          mark="table{\\n\\n...\\n\\n}table"
+          d=dob_src.is.to_s
+          instruct=s_mark=''
+          if @md.opt.act[:maintenance][:set]==:on
+            instruct=%{\n# tables are a text block with an opening and closing marker, } \
+            + %{the content of which should remain unwrapped}
+            s_mark="\n# " + %{"\\n\\n#{mark}\\n\\n"}
+          end
+          desc="#{d}#{s_mark}#{instruct}"
+          orig=dob_src.obj
+          orig=orig.gsub(/#{Mx[:tc_c]}/,"\n")
+          trans=(dob_trn=='') ? '' : dob_trn.obj
+          trans=trans.gsub(/#{Mx[:tc_c]}/,"\n")
+          util=pot_structure_wrap(desc,orig,trans)
+          unwrapped=util.no_line_wrap_block
+          @pot[:body] << unwrapped << br
         end
-        desc="#{d}#{s_mark}#{instruct}"
-        orig=dob_src.obj
-        orig=orig.gsub(/#{Mx[:tc_c]}/,"\n")
-        trans=(dob_trn=='') ? '' : dob_trn.obj
-        trans=trans.gsub(/#{Mx[:tc_c]}/,"\n")
-        util=pot_structure(desc,orig,trans)
-        unwrapped=util.no_line_wrap_block
-        @pot[:body] << unwrapped << br
-      end
-      def pot_structure_idx_markup(idx)
-        struct=['={']
-        idx.sort.each do |x|
-          x.each_with_index do |y,i0|
-            case y
-            when String
-              struct << ';' unless struct[-1] =~/=\{/
-              struct << y
-              if x[i0+1].class == Hash \
-              and x[i0+1][:sub].length > 0
-                struct << ':'
-              end
-            when Hash
-              if y[:plus].to_i > 0
-                struct << '+' + y[:plus].to_s
-              end
-              if y[:sub].length > 0
-                y[:sub].each_with_index do |z,i1|
-                  z.each_with_index do |a,i2|
-                    #p a
-                    if z.length > 0
-                      struct << a[0]
-                      if a[1][:plus].to_i > 0
-                        struct << '+' + a[1][:plus].to_s
-                      end
-                      if (i1 + 1) < y[:sub].length
-                        struct << '|'
+        def idx_markup(idx)
+          struct=['={']
+          idx.sort.each do |x|
+            x.each_with_index do |y,i0|
+              case y
+              when String
+                struct << ';' unless struct[-1] =~/=\{/
+                struct << y
+                if x[i0+1].class == Hash \
+                and x[i0+1][:sub].length > 0
+                  struct << ':'
+                end
+              when Hash
+                if y[:plus].to_i > 0
+                  struct << '+' + y[:plus].to_s
+                end
+                if y[:sub].length > 0
+                  y[:sub].each_with_index do |z,i1|
+                    z.each_with_index do |a,i2|
+                      #p a
+                      if z.length > 0
+                        struct << a[0]
+                        if a[1][:plus].to_i > 0
+                          struct << '+' + a[1][:plus].to_s
+                        end
+                        if (i1 + 1) < y[:sub].length
+                          struct << '|'
+                        end
                       end
                     end
                   end
@@ -858,31 +876,32 @@ GSUB
               end
             end
           end
+          struct << '}'
+          #puts struct.join
+          struct.join
         end
-        struct << '}'
-        #puts struct.join
-        struct.join
-      end
-      def pot_structure_idx(dob_src='',dob_trn='')                             #% used for book index but broken as original markup lost, already abstracted, fix
-        mark="={ ... }"
-        instruct=s_mark=''
-        if @md.opt.act[:maintenance][:set]==:on
-          instruct=%{\n# the book index should be attached unwrapped to the preceding text block } \
-          + %{(there should be a new line, but no empty line)}
-          s_mark="\n# " + %{"\\n#{mark}\\n\\n"}
-        end
-        d='book-idx'
-        desc="#{d}#{s_mark}#{instruct}"
-        orig=pot_structure_idx_markup(dob_src.idx) #'={' + dob_src.idx + '}'
-        trans=if defined? dob_trn.idx \
-        and not dob_trn.idx.nil? \
-        and not dob_trn.idx.empty?
-          pot_structure_idx_markup(dob_trn.idx) #'={' + dob_trn.idx + '}'
-        else ''
+        def idx(dob_src='',dob_trn='')                             #% used for book index but broken as original markup lost, already abstracted, fix
+          mark="={ ... }"
+          instruct=s_mark=''
+          if @md.opt.act[:maintenance][:set]==:on
+            instruct=%{\n# the book index should be attached unwrapped to the preceding text block } \
+            + %{(there should be a new line, but no empty line)}
+            s_mark="\n# " + %{"\\n#{mark}\\n\\n"}
+          end
+          d='book-idx'
+          desc="#{d}#{s_mark}#{instruct}"
+          orig=pot_structure.idx_markup(dob_src.idx) #'={' + dob_src.idx + '}'
+          trans=if defined? dob_trn.idx \
+          and not dob_trn.idx.nil? \
+          and not dob_trn.idx.empty?
+            pot_structure.idx_markup(dob_trn.idx) #'={' + dob_trn.idx + '}'
+          else ''
+          end
+          util=pot_structure_wrap(desc,orig,trans)
+          unwrapped=util.no_line_wrap_block
+          @pot[:body] << unwrapped << br
         end
-        util=pot_structure(desc,orig,trans)
-        unwrapped=util.no_line_wrap_block
-        @pot[:body] << unwrapped << br
+        self
       end
       def pot_markup(data_src,data_trn)
         #@endnotes,@copen,@pot_contents_close=Array.new(3){[]}
@@ -1003,24 +1022,24 @@ GSUB
           end
           case dob_src.is
           when :heading
-            pot_structure_heading(dob_src,notes_s,dob_trn,notes_t)
+            pot_structure.heading(dob_src,notes_s,dob_trn,notes_t)
           when :para
-            pot_structure_para(dob_src,notes_s,dob_trn,notes_t)
+            pot_structure.para(dob_src,notes_s,dob_trn,notes_t)
           when :group
-            pot_structure_group(dob_src,notes_s,dob_trn,notes_t)
+            pot_structure.group(dob_src,notes_s,dob_trn,notes_t)
           when :block
-            pot_structure_block(dob_src,notes_s,dob_trn,notes_t)
+            pot_structure.block(dob_src,notes_s,dob_trn,notes_t)
           when :verse
-            pot_structure_verse(dob_src,notes_s,dob_trn,notes_t)
+            pot_structure.verse(dob_src,notes_s,dob_trn,notes_t)
           when :code
-            pot_structure_code(dob_src,notes_s,dob_trn,notes_t)
+            pot_structure.code(dob_src,notes_s,dob_trn,notes_t)
           when :table
-            pot_structure_table(dob_src,notes_s,dob_trn,notes_t)
+            pot_structure.table(dob_src,notes_s,dob_trn,notes_t)
           end
           if defined? dob_src.idx \
           and not dob_src.idx.nil? \
           and not dob_src.idx.empty?
-            pot_structure_idx(dob_src,dob_trn)
+            pot_structure.idx(dob_src,dob_trn)
           end
           dob_src='' if (dob_src.obj =~/<a name="n\d+">/ \
           and dob_src.obj =~/^(-\{{2}~\d+|<!e[:_]\d+!>)/) # -endnote
@@ -1031,83 +1050,8 @@ GSUB
         end
         #[dob_src,dob_trn]
       end
-      def markup(dob)                                                          # used for major markup instructions
-        SiSU_Env::InfoEnv.new(@md.fns)
-        dob.obj=dob.obj.
-          gsub(/#{Mx[:fa_bold_o]}(.+?)#{Mx[:fa_bold_c]}/,
-            "#{Px[:po_bold_o]}\\1#{Px[:po_bold_c]}").
-          gsub(/#{Mx[:fa_italics_o]}(.+?)#{Mx[:fa_italics_c]}/,
-            "#{Px[:po_italics_o]}\\1#{Px[:po_italics_c]}").
-          gsub(/#{Mx[:fa_underscore_o]}(.+?)#{Mx[:fa_underscore_c]}/,
-            "#{Px[:po_underscore_o]}\\1#{Px[:po_underscore_c]}").
-          gsub(/#{Mx[:fa_subscript_o]}(.+?)#{Mx[:fa_subscript_c]}/,
-            "#{Px[:po_subscript_o]}\\1#{Px[:po_subscript_c]}").
-          gsub(/#{Mx[:fa_superscript_o]}(.+?)#{Mx[:fa_superscript_c]}/,
-            "#{Px[:po_superscript_o]}\\1#{Px[:po_superscript_c]}").
-          gsub(/#{Mx[:fa_insert_o]}(.+?)#{Mx[:fa_insert_c]}/,
-            "#{Px[:po_insert_o]}\\1#{Px[:po_insert_c]}").
-          gsub(/#{Mx[:fa_cite_o]}(.+?)#{Mx[:fa_cite_c]}/,
-            "#{Px[:po_cite_o]}\\1#{Px[:po_cite_c]}").
-          gsub(/#{Mx[:fa_strike_o]}(.+?)#{Mx[:fa_strike_c]}/,
-            "#{Px[:po_strike_o]}\\1#{Px[:po_strike_c]}").
-          gsub(/#{Mx[:fa_monospace_o]}(.+?)#{Mx[:fa_monospace_c]}/,
-            "#{Px[:po_monospace_o]}\\1#{Px[:po_monospace_c]}")
-        notes=''
-        unless dob.is==:code
-          dob.obj=dob.obj.
-            gsub(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}#{Mx[:rel_o]}\S+?#{Mx[:rel_c]}/,'\1').
-            gsub(/#{Mx[:url_o]}_(\S+?)#{Mx[:url_c]}/,'\1').
-            gsub(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/,
-              '\1 [link: <\2>]').
-            gsub(/#{Mx[:lnk_o]}(.+?)#{Mx[:lnk_c]}image/,
-              '\1 [link: local image]').
-            gsub(/#{Mx[:url_o]}(\S+?)#{Mx[:url_c]}/,'\1')
-          notes=extract_endnotes(dob)
-          #% ### footnotes current state - extracted
-          dob.obj=dob.obj.
-            gsub(/#{Mx[:en_a_o]}([\d]+)\s+(?:.+?)#{Mx[:en_a_c]}/,'~^').   # endnote marker marked up
-          #% ### footnotes current state - keep inline
-          #dob.obj.gsub!(/#{Mx[:en_a_o]}[\d]+\s+(.+?)#{Mx[:en_a_c]}/,'~{ \1 }~')     # inline endnote with marker marked up
-            gsub(/#{Mx[:en_b_o]}[\d]+\s+(.+?)#{Mx[:en_b_c]}/,
-              '~[ \1 ]~').     # inline endnote with marker marked up
-            gsub(/#{Mx[:en_a_o]}([*+]+)\s+(.+?)#{Mx[:en_a_c]}/,
-              '~{\1 \2 }~'). # inline endnote with marker marked up
-            gsub(/#{Mx[:en_b_o]}([*+]+)\s+(.+?)#{Mx[:en_b_c]}/,
-              '~[\1 \2 ]~'). # inline endnote with marker marked up
-            gsub(/#{Mx[:gl_o]}(?:#lt|#060)#{Mx[:gl_c]}/,'<').
-            gsub(/#{Mx[:gl_o]}(?:#gt|#062)#{Mx[:gl_c]}/,'>').
-            gsub(/#{Mx[:gl_o]}#(?:038|amp)#{Mx[:gl_c]}/,'&').
-            gsub(/#{Mx[:gl_o]}#033#{Mx[:gl_c]}/,'!').
-            gsub(/#{Mx[:gl_o]}#035#{Mx[:gl_c]}/,'#').
-            gsub(/#{Mx[:gl_o]}#042#{Mx[:gl_c]}/,'*').
-            gsub(/#{Mx[:gl_o]}#045#{Mx[:gl_c]}/,'-').
-            gsub(/#{Mx[:gl_o]}#047#{Mx[:gl_c]}/,'/').
-            gsub(/#{Mx[:gl_o]}#095#{Mx[:gl_c]}/,'_').
-            gsub(/#{Mx[:gl_o]}#123#{Mx[:gl_c]}/,'{').
-            gsub(/#{Mx[:gl_o]}#125#{Mx[:gl_c]}/,'}').
-            gsub(/#{Mx[:gl_o]}#126#{Mx[:gl_c]}/,'~').
-            gsub(/#{Mx[:gl_o]}#169#{Mx[:gl_c]}/,'©')
-        end
-        dob.obj=if dob.of==:block                                   # watch
-          dob.obj.gsub(/#{Mx[:gl_o]}●#{Mx[:gl_c]}/,"* ").
-            gsub(/#{Mx[:br_line]}|#{Mx[:br_nl]}/,"\n")
-        else dob.obj.gsub(/#{Mx[:br_line]}|#{Mx[:br_nl]}/,"\n\n")
-        end
-        if dob.is==:code
-          dob.obj=dob.obj.gsub(/(^|[^}])_([<>])/m,'\1\2'). # _> _<
-            gsub(/(^|[^}])_([<>])/m,'\1\2') # _<_<
-        end
-        dob.obj=dob.obj.gsub(/#{Mx[:br_page]}\s*|#{Mx[:br_page_new]}/,'').                     # remove page breaks
-          gsub(/#{Mx[:url_o]}_(\S+?)#{Mx[:url_c]}/,'\1').
-          gsub(/<a href=".+?">(.+?)<\/a>/m,'\1').
-          gsub(/#{Mx[:mk_o]}:name#(\S+?)#{Mx[:mk_c]}/,'').                       # remove name links
-          gsub(/&nbsp;|#{Mx[:nbsp]}/,' ').                                       # decide on
-          gsub(/(?:^|[^_\\])#{Mx[:lnk_o]}(\S+?\.(?:png|jpg|gif)) .+?#{Mx[:lnk_c]}#{Mx[:url_o]}\S+?#{Mx[:url_c]}/,
-            '    [ \1 ]'). #"[ #{dir.url.images_local}\/\\1 ]")
-          gsub(/(?:^|[^_\\])#{Mx[:lnk_o]}(\S+?\.(?:png|jpg|gif)) .+?#{Mx[:lnk_c]}image/,
-            '    [ \1 ]'). #"[ #{dir.url.images_local}\/\\1 ]")
-          gsub(/(?:^|[^_\\])\{\s*\S+?\.(?:png|jpg|gif)\s+.+?"(.*?)"\s*\}\S+/,
-            '[image: "\1"]')
+      def markup(dob)
+        dob,notes=objects.textface_marks_po4a(dob,:separate)
         [dob,notes]
       end
       def publish(fn,pot)
@@ -1129,7 +1073,7 @@ GSUB
         @file=SiSU_Env::FileOp.new(md,fn)
       end
       def po4a                                                                 #%pot output
-        file_pot=(@md.opt.f_pth[:lng] ==@md.opt.lng_base) \
+        file_pot=(@md.opt.f_pth[:lng] == @md.opt.lng_base) \
         ? @file.write_file.pot
         : @file.write_file.po
         @sisu=[]
@@ -1162,7 +1106,7 @@ GSUB
           unless FileTest.directory?(@file.output_path.pot_git.dir)
             git.create_file_structure_git
           end
-          if @md.opt.f_pth[:lng] ==@md.opt.lng_base
+          if @md.opt.f_pth[:lng] == @md.opt.lng_base
             FileUtils::cp(
               @file.place_file.pot.dir,
               @file.output_path.pot_git.dir
@@ -1193,3 +1137,7 @@ where no ocn appropriately use ~# or -# or indeed 1~name-
 
 comments in document, what to do about them, not sure they are currently
 retained in dal, could be quite valuable to keep
+
+Translate Shell
+http://www.soimort.org/translate-shell/
+translate.google.com
diff --git a/lib/sisu/develop/po4a_set.rb b/lib/sisu/develop/po4a_set.rb
index 2ae73102..d56175fe 100644
--- a/lib/sisu/develop/po4a_set.rb
+++ b/lib/sisu/develop/po4a_set.rb
@@ -57,7 +57,8 @@
 module SiSU_Po4aUtils
   class Wrap
     def initialize(md,orig='',trans='',is_desc='',n_char_max=76,n_indent=0,n_hang=nil)
-      @md,@orig,@trans,@is_desc,@n_char_max,@n_indent=md,orig,trans,is_desc,n_char_max,n_indent
+      @md,@orig,@trans,@is_desc,@n_char_max,@n_indent=
+       md, orig, trans, is_desc, n_char_max, n_indent
       @n_char_max_extend = n_char_max
       @br="\n"
       @n_hang=n_hang ? n_hang : @n_indent
@@ -66,7 +67,8 @@ module SiSU_Po4aUtils
     end
     def line_wrap
       space=' '
-      spaces_indent,spaces_hang="#{@br}#{space*@n_indent}",space*@n_hang
+      spaces_indent,spaces_hang=
+        "#{@br}#{space*@n_indent}",space*@n_hang
       pot,i=[],0
       pot_array=(@trans.empty?) ? [@orig] : [@orig,@trans]
       pot_array.each do |pa|
@@ -76,7 +78,7 @@ module SiSU_Po4aUtils
         @oldword='' #REMOVE @oldword
         pa=pa.gsub(/<br>/,' <br> ').
           gsub(/#{Mx[:br_nl]}/,"\n\n")
-        words=pa.scan(/\n\n|<br>|\S+/m)
+        words=pa.scan(/\n\n|\\\\\\|<br>|\S+/m)
         while words != ''
           word=words.shift
           if not word
diff --git a/lib/sisu/develop/se_file_op.rb b/lib/sisu/develop/se_file_op.rb
index 1555d119..585a1c12 100644
--- a/lib/sisu/develop/se_file_op.rb
+++ b/lib/sisu/develop/se_file_op.rb
@@ -468,8 +468,8 @@ module SiSU_File_Op
         fn=base_filename.pot
         make_file(path,fn)
       end
-      def po
-        path=output_path.po.dir
+      def po(lng=@md.opt.lng)
+        path=output_path.po(lng).dir
         make_path(path)
         fn=base_filename.po
         make_file(path,fn)
@@ -1747,17 +1747,18 @@ module SiSU_File_Op
         end
         self
       end
-      def po
+      def po(lng=@md.opt.lng)
+        @lng=lng
         def dir
           output_path.base.dir + '/' \
             + Gt[:src] + '/' \
             + @md.opt.fng + '/po4a/po/' \
-            + @md.opt.lng
+            + @lng
         end
         def url
           output_path.base.url + '/po4a/' \
             + @md.fnb + '/po/' \
-            + @md.opt.lng
+            + @lng
         end
         self
       end
-- 
cgit v1.2.3