changeset 26:16f91684686b default tip

Upgrade to python 3. Keep python 2/3 compatibility
author Miguel Ángel Bárcena Rodríguez <miguelangel@obraencurso.es>
date Tue, 18 Jun 2019 17:50:23 +0200
parents 189f8274aecd
children
files Generic/base.py Generic/fiebdc.py Generic/globalVars.py Generic/utils.py Gtk/gui.py mo/es/LC_MESSAGES/pyArq-Presupuestos.mo mo/pyArq-Presupuestos.es.po mo/pyArq-Presupuestos.pot pyArq-Presupuestos.py
diffstat 9 files changed, 1918 insertions(+), 1504 deletions(-) [+]
line wrap: on
line diff
--- a/Generic/base.py	Mon May 20 13:18:33 2019 +0200
+++ b/Generic/base.py	Tue Jun 18 17:50:23 2019 +0200
@@ -263,7 +263,9 @@
 
 # Modules
 # python 2/3 compatibility
-#from __future__ import absolute_import, division, print_function, unicode_literals
+from __future__ import absolute_import, division, print_function, unicode_literals
+from builtins import str as text
+from six import text_type
 
 import re
 import datetime
@@ -277,7 +279,7 @@
 # Translatable global Vars
 
 authors = ["Miguel Ángel Bárcena Rodríguez"]
-copyright = "Copyright \xc2\xa9 2019 Autoras de Pyarq Presupuestos"
+copyright = "Copyright © 2019 Autoras de Pyarq Presupuestos"
 website = "http://pyarq.obraencurso.es/pyarq-Presupuestos"
 website_label = "pyarq Presupuestos Web"
 comments = _("""
@@ -418,7 +420,9 @@
         Sets the code, must be a valid code
         """
         if not utils.is_valid_code(code)[0]:
-            raise ValueError(utils.mapping(_("Invalid code: $1"),(str(code),)))
+            _uni = utils.mapping(_("Invalid code: $1"),(code,))
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         self.__code = code
 
     def getSynonyms(self):
@@ -433,12 +437,16 @@
             - the items must be valid codes
         """
         if not isinstance(synonyms, list):
-            raise TypeError( utils.mapping(_("Synonyms ($1) must be a list, " \
-                  "code: $2"), (str(synonyms), str(self.__code))) )
+            _tuni = _("Synonyms ($1) must be a list, code: $2")
+            _uni = utils.mapping(_tuni, (synonyms, self.__code))
+            _str = _uni.encode("utf-8")
+            raise TypeError(_str)
         for code in synonyms:
             if not utils.is_valid_code(code)[0]:
-                raise ValueError( utils.mapping(_("Invalid Code in synomyms "\
-                      "list ($1) code: $2"), (str(code), str(self.__code))) )
+                _tuni = _("Invalid Code in synomyms list ($1) code: $2")
+                _uni = utils.mapping(_tuni, (code, self.__code))
+                _str = _uni.encode("utf-8")
+                raise ValueError(_str)
         self.__synonyms = synonyms
 
     def getRecordType(self):
@@ -467,9 +475,11 @@
         Set the unit of measure
         The unit must be a string.
         """
-        if not isinstance(unit, str):
-            raise TypeError( utils.mapping(_("Unit ($1) must be a string: $2"),
-                  (str(unit), str(self.__code))) )
+        if not isinstance(unit, text_type):
+            _tuni = _("Unit ($1) must be a text string: $2")
+            _uni = utils.mapping(_tuni, (unit, self.__code))
+            _str = _uni.encode("utf-8")
+            raise TypeError(_str)
         self.__unit = unit
 
     def getSummary(self):
@@ -481,9 +491,11 @@
         Set the summary of a record
         The summary must be a string.
         """
-        if not isinstance(summary, str):
-            raise TypeError( utils.mapping(_("Summary ($1) must be a string: "\
-                  "$1"), (str(summary), str(self.__code))) )
+        if not isinstance(summary, text_type):
+            _tuni = _("Summary ($1) must be a text string: $1")
+            _uni = utils.mapping(_tuni, (summary, self.__code))
+            _str = _uni.encode("utf-8")
+            raise TypeError(_str)
         self.__summary = summary
 
     def getPrices(self):
@@ -499,8 +511,10 @@
             - the first item: price must be a float
         """
         if not isinstance(prices, list):
-            raise TypeError( utils.mapping(_("Prices ($1) must be a list: $2"),
-                  (str(prices), str(self.__code))) )
+            _tuni = _("Prices ($1) must be a list: $2")
+            _uni = utils.mapping(_tuni, (text(prices), self.__code))
+            _str = _uni.encode("utf-8")
+            raise TypeError(_str)
         for index in range(len(prices)):
             _price_date = prices[index]
             _price_date = self._validate_price_date(_price_date, decimals)
@@ -520,13 +534,17 @@
 
     def _validate_price_date(self, price_date, decimals):
         if not isinstance(price_date, list) and len(price_date) == 2:
-            raise ValueError( utils.mapping(_("Price ($1) must be a list"\
-                  " with two items: $2"), (str(price_date), str(self.__code))) )
+            _tuni = _("Price ($1) must be a list with two items: $2")
+            _uni = utils.mapping(_tuni, (text(price_date), self.__code))
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         _price = price_date[0]
         _date = price_date[1]
         if not isinstance(_price, float):
-            raise TypeError( utils.mapping(_("Price must be a float "\
-                      "number: $1"), (str(_price),)) )
+            _tuni = ("Price must be a float number: $1")
+            _uni = utils.mapping(_tuni, (text(_price),))
+            _str = _uni.encode("utf-8")
+            raise TypeError(_str)
         _D = abs(decimals.getD(self.recordType))
         _price = round(_price, _D)
         price_date[0] = _price
@@ -535,19 +553,23 @@
 
     def getPrice(self, index_price):
         if len(self.__prices) <= index_price:
-            raise IndexError( _("The record do not have this Price. Code: %s"
-                                % self.__code) )
+            _tuni = _("The record do not have this Price. Code: $1")
+            _uni = utils.mapping(_tuni, (self.__code,))
+            _str = _uni.encode("utf-8")
+            raise IndexError(_str)
         return self.__prices[index_price][0]
 
     def getDate(self, index_price):
         if len(self.__prices) <= index_price:
-            raise IndexError( _("The record do not have this Price") )
+            _tuni = _("The record do not have this Price")
+            _str = _tuni.encode("utf-8")
+            raise IndexError(_str)
         return self.__prices[index_price][1] 
 
     def getParents(self):
         return self.__parents
 
-    def setParents(self,parents):
+    def setParents(self, parents):
         """setParents(parents)
         
         Sets the list of parents codes of the record.
@@ -556,12 +578,16 @@
             - the items must be valid codes
         """
         if not isinstance(parents, list):
-            raise TypeError( utils.mapping(_("Parents ($1) must be a list: $2"),
-                  (str(parents), str(self.__code))) )
+            _tuni = _("Parents ($1) must be a list: $2")
+            _uni = utils.mapping(_tuni, (text(parents), self.__code))
+            _str = _uni.encode("utf-8")
+            raise TypeError(_str)
         for parent in parents:
             if not utils.is_valid_code(parent)[0]:
-                raise ValueError(utils.mapping(_("Invalid parent code ($1) " \
-                      "in the record: $2"), (str(padre), str(self.__code))) )
+                _tuni = _("Invalid parent code ($1) in the record: $2")
+                _uni = utils.mapping(_tuni, (padre, self.__code))
+                _str = _uni.encode("utf-8")
+                raise ValueError(_str)
         self.__parents = parents
 
     def appendParent(self, parent):
@@ -572,8 +598,10 @@
 
         """
         if not utils.is_valid_code(parent)[0]:
-            raise ValueError( utils.mapping(_("Invalid parent code ($1) " \
-                  "in the record: $2"), (str(parent), str(self.__code))) )
+            _tuni = _("Invalid parent code ($1) in the record: $2")
+            _uni = utils.mapping(_tuni, (parent, self.__code))
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         self.__parents.append(parent)
 
     def getchildren(self):
@@ -588,13 +616,16 @@
             - the items must be instances of Decomposition class
         """
         if not isinstance(children, list):
-            raise TypeError( utils.mapping(_("children ($1) must be a list, "\
-                  "record: $2"), (str(children), str(self.__code))) )
+            _tuni = _("children ($1) must be a list, record: $2")
+            _uni = utils.mapping(_tuni, (text(children), self.__code))
+            _str = _uni.encode("utf-8")
+            raise TypeError(_str)
         for _child in children:
             if not isinstance(_child, Decomposition):
-                raise ValueError( utils.mapping(_("child ($1) must be a "\
-                      "Decomposition object, record: $2"),
-                      (str(_child), str(self.__code))) )
+                _tuni = _("child ($1) must be a Decomposition object, record: $2")
+                _uni = utils.mapping(_tuni, (text(_child), self.__code))
+                _str = _uni.encode("utf-8")
+                raise ValueError(_str)
             _record_code = self.code
             for _measure_list in [_child.budgetMeasures, _child.certification,
                                   _child.real_cost, _child.cost_goals,
@@ -645,9 +676,11 @@
         Sets the text of the record
         It must be a string
         """
-        if not isinstance(text, str):
-            raise TypeError( utils.mapping(_("Text ($1) must be a string, "\
-                  "record: $2"), (str(text), str(self.__code))) )
+        if not isinstance(text, text_type):
+            _tuni = _("Text ($1) must be a text string, record: $2")
+            _uni = utils.mapping(_tuni, (text, self.__code))
+            _str = _uni.encode("utf-8")
+            raise TypeError(_str)
         self.__text = text
 
     def getSheet(self):
@@ -659,7 +692,9 @@
         Sets the sheet of condition object
         """
         if not isinstance(sheet, Sheet):
-            raise ValueError( _("sheet must be a Sheet instance") )
+            _tuni = _("sheet must be a Sheet instance")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         self.__sheet = sheet
 
     def getFiles(self):
@@ -671,8 +706,10 @@
         Sets the files list
         """
         if not isinstance(files, list):
-            raise ValueError( utils.mapping(_("files must be a list: $1"),
-                                              str(files)) )
+            _tuni = _("files must be a list: $1")
+            _uni = utils.mapping(_tuni, text(files))
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         _files = []
         for file in files:
             if isinstance(file, File):
@@ -682,12 +719,16 @@
                 _type = file[1]
                 _description = file[2]
                 if not os.path.exists(file[0]):
-                    raise ValueError( _("Incorrect path") )
+                    _tuni = _("Incorrect path")
+                    _str = _tuni.encode("utf-8")
+                    raise ValueError(_str)
                 _file = File(file_path, type_, description)
                 _files.append(_file)
             else:
-                raise ValueError( utils.mapping(_(
-                      "file must be a list or a File object: $1"),str(file)) )
+                _tuni = _("file must be a list or a File object: $1")
+                _uni = utils.mapping(_tuni, file)
+                _str = _uni.encode("utf-8")
+                raise ValueError(_str)
         self.__files = _files
 
     def addFile(self, file_path, type_, description):
@@ -696,7 +737,9 @@
         Add a file to a record instance
         """
         if not os.path.exists(file_path):
-            raise ValueError( _("Incorrect path") )
+            _tuni = _("Incorrect path")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         _name = os.path.basename(file_path)
         _isin = False
         for _ofile in self.__files:
@@ -715,13 +758,17 @@
         Sets the labels list of a record
         """
         if not isinstance(labels, list):
-            raise ValueError( _("labels must be a list") )
+            _tuni = _("labels must be a list")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         _labels = []
         for _label in labels:
-            if isinstance(_label, str):
+            if isinstance(_label, text_type):
                 _labels.append(_label)
             else:
-                raise ValueError( _("label must be a string") )
+                _tuni = _("label must be a text string")
+                _str = _tuni.encode("utf-8")
+                raise ValueError(_str)
         self.__labels = _labels
 
     def addLabel(self, label):
@@ -729,8 +776,10 @@
         
         Add a label to a record instance
         """
-        if not isinstance(label, str):
-            raise ValueError( _("Label must be a string") )
+        if not isinstance(label, text_type):
+            _tuni = _("Label must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         if not label in self.__labels:
             self.__labels.append(label)
 
@@ -978,7 +1027,9 @@
 
     def setPosition(self, position):
         if not isinstance(position, int):
-            raise ValueError( _("Position must be a integer") )
+            _tuni = _("Position must be a integer")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         self.__position = position
 
     def getCode(self):
@@ -992,11 +1043,14 @@
 
     def setBudgetMeasures(self, budgetMeasures):
         if not isinstance(budgetMeasures, list):
-            raise ValueError( _("BudgetMeasures atribute must be a list") )
+            _tuni = _("BudgetMeasures atribute must be a list")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         for _measure in budgetMeasures:
             if not isinstance(_measure, Measure):
-                raise ValueError( _("BudgetMeasures item must be a Measure "/
-                                    "object") )
+                _tuni = _("BudgetMeasures item must be a Measure object")
+                _str = _tuni.encode("utf-8")
+                raise ValueError(_str)
         self.__budgetMeasures = budgetMeasures
 
     def getCertification(self):
@@ -1004,7 +1058,9 @@
 
     def setCertification(self, certification):
         if not (certification is None or isinstance(certification, list)):
-            raise ValueError(_("Certification atribute must be a list or None"))
+            _tuni = _("Certification atribute must be a list or None")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         self.__certification = certification
 
     def getRealCost(self):
@@ -1012,7 +1068,9 @@
 
     def setRealCost(self, real_cost):
         if not (real_cost is None or  isinstance(real_cost, list)):
-            raise ValueError( _("Real cost atribute must be a list or None") )
+            _tuni =_("Real cost atribute must be a list or None")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         self.__real_cost = real_cost
 
     def getCostGoals(self):
@@ -1020,7 +1078,9 @@
 
     def setCostGoals(self, cost_goals):
         if not (cost_goals is None or  isinstance(cost_goals, list)):
-            raise ValueError( _("Cost goals atribute must be a list or None") )
+            _tuni = _("Cost goals atribute must be a list or None")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         self.__cost_goals = cost_goals
 
     def getCostPlanned(self):
@@ -1028,7 +1088,9 @@
 
     def setCostPlanned(self, cost_planned):
         if not (cost_planned is None or  isinstance(cost_planned, list)):
-            raise ValueError(_("Cost Planned atribute must be a list or None"))
+            _tuni = _("Cost Planned atribute must be a list or None")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         self.__cost_planned = cost_planned
 
     position = property(getPosition, setPosition, None,
@@ -1121,8 +1183,10 @@
 
     def setMeasure(self, measure, decimals):
         if not isinstance(measure, float):
-            raise ValueError( utils.mapping(_("Measure must be a float "\
-                  "number. Type: $1"), (type(measure),)) )
+            _tuni = _("Measure must be a float number. Type: $1")
+            _uni = utils.mapping(_tuni, (type(measure),))
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         # TODO: test after
         _DS = abs(decimals.DS)
         measure = round(measure, _DS)
@@ -1133,10 +1197,14 @@
 
     def setLines(self, lines):
         if not isinstance(lines, list):
-            raise ValueError( _("Lines must be a list") )
+            _tuni = _("Lines must be a list")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         for _line in lines:
             if not isinstance(_line, MeasureLine):
-                raise ValueError( _("Line must be a MeasureLine objetc") )
+                _tuni = _("Line must be a MeasureLine objetc")
+                _str = _tuni.encode("utf-8")
+                raise ValueError(_str)
         self.__lines = lines
 
     def getLabel(self):
@@ -1147,8 +1215,10 @@
 
     def setFactor(self, factor, decimals, recordType):
         if not isinstance(factor, float):
-            raise ValueError( utils.mapping(_("Factor must be a float number "\
-                  "|$1|"), (str(factor),)) )
+            _tuni = _("Factor must be a float number |$1|")
+            _uni = utils.mapping(_tuni, (text(factor),))
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         # TODO: test after
         _DF = abs(decimals.getDF(recordType))
         factor = round(factor, _DF)
@@ -1159,7 +1229,9 @@
 
     def setYield(self, yield_, decimals, recordType):
         if not isinstance(yield_, float):
-            raise ValueError( _("Yield must be a float number") )
+            _tuni = _("Yield must be a float number")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         # TODO: test after
         _DR = abs(decimals.getDR(recordType))
         yield_ = round(yield_, _DR)
@@ -1170,7 +1242,9 @@
 
     def setFixed(self, fixed, decimals):
         if not isinstance(fixed, bool):
-            raise ValueError( _("Fixed must be boolean object") )
+            _tuni = _("Fixed must be boolean object")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         self.__fixed = fixed
         self.updateYield(decimals)
 
@@ -1240,8 +1314,10 @@
         elif type_ == "A":
             self.lines.extend(_lines)
         else:
-            raise ValueError( utils.mapping(_("Type must be M or A. Type: $1"),
-                                            (str(type_),)) )
+            _tuni = _("Type must be M or A. Type: $1")
+            _uni = utils.mapping(_tuni, (type_,))
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         self.calculateMeasure(decimals, recordType)
 
     def calculateMeasure(self, decimals, recordType):
@@ -1384,17 +1460,20 @@
 
     def setParcialSubtotal(self, parcial_subtotal, decimals):
         if not isinstance(parcial_subtotal, float):
-            raise ValueError( utils.mapping(_(" Parcial Subtotal must be a "\
-                      "float number. Parcial: $1"), (str(parcial_subtotal),)) )
+            _tuni = _("Parcial Subtotal must be a float number. Parcial: $1")
+            _uni = utils.mapping(_tuni, (text(parcial_subtotal),))
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         _DS = abs(decimals.DS)
         parcial_subtotal = round(parcial_subtotal, _DS)
         self.__parcial_subtotal = parcial_subtotal
 
     def setAcumulatedSubtotal(self, acumulated_subtotal, decimals):
         if not isinstance(acumulated_subtotal, float):
-            raise ValueError( utils.mapping(_(" Acumulated Subtotal must be "\
-                      "a float number. Parcial: $1"),
-                     (str(acumulated_subtotal),)) )
+            _tuni = _("Acumulated Subtotal must be a float number. Parcial: $1")
+            _uni = utils.mapping(_tuni, (text(acumulated_subtotal),))
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         _DS = abs(decimals.DS)
         acumulated_subtotal = round(acumulated_subtotal, _DS)
         self.__acumulated_subtotal = acumulated_subtotal
@@ -1428,21 +1507,27 @@
 
     def setLineType(self, type_):
         if not type_ in [0, 1, 2, 3]:
-            raise ValueError( utils.mapping(_("Invalid measure line type ($1)"),
-                  (str(type_),)) )
+            _tuni = _("Invalid measure line type ($1)")
+            _uni = utils.mapping(_tuni, (type_,))
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         self.__lineType = type_
 
     def setComment(self, comment):
-        if not isinstance(comment, str):
-            raise ValueError( utils.mapping(_("Measure Comment must be a "\
-                  "string ($1)"), (str(comment),)) )
+        if not isinstance(comment, text_type):
+            _tuni = ("Measure Comment must be a text string ($1)")
+            _uni = utils.mapping(_tuni, (comment,))
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         self.__comment = comment
 
     def setUnits(self, units, decimals):
         if units != "":
             if not isinstance(units, float):
-                raise ValueError( utils.mapping(_("Invalid Measure Units ($1)"),
-                      (str(units),)) )
+                _tuni = _("Invalid Measure Units ($1)")
+                _uni = utils.mapping(_tuni, (text(units),))
+                _str = _uni.encode("utf-8")
+                raise ValueError(_str)
             _DN = abs(decimals.DN)
             units = round(units, _DN)
         self.__units = units
@@ -1454,8 +1539,10 @@
     def setLength(self, length, decimals):
         if length != "":
             if not isinstance(length, float):
-                raise ValueError( utils.mapping(_("Invalid Measure length ($1)"),
-                      (str(units),)) )
+                _tuni = _("Invalid Measure length ($1)")
+                _uni = utils.mapping(_tuni, (text(length),))
+                _str = _uni.encode("utf-8")
+                raise ValueError(_str)
             _DD = abs(decimals.DD)
             length = round(length, _DD)
         self.__length = length
@@ -1467,8 +1554,10 @@
     def setWidth(self, width, decimals):
         if width != "":
             if not isinstance(width, float):
-                raise ValueError( utils.mapping(_("Invalid Measure Width ($1)"),
-                      (str(units),)) )
+                _tuni = _("Invalid Measure Width ($1)")
+                _uni =  utils.mapping(_tuni, (text(units),))
+                _str = _uni.encode("utf-8")
+                raise ValueError(_str)
             _DD = abs(decimals.DD)
             width = round(width, _DD)
         self.__width = width
@@ -1480,8 +1569,10 @@
     def setHeight(self, height, decimals):
         if height != "":
             if not isinstance(height, float):
-                raise ValueError( utils.mapping(_("Invalid Measure Height ($1)"),
-                      (str(height),)) )
+                _tuni = _("Invalid Measure Height ($1)")
+                _uni = utils.mapping(_tuni, (text(height),))
+                _str = _uni.encode("utf-8")
+                raise ValueError(_str)
             _DD = abs(decimals.DD)
             height = round(height, _DD)
         self.__height = height
@@ -1491,12 +1582,16 @@
             pass
 
     def setFormula(self, formula, decimals):
-        if not isinstance(formula, str):
-            raise ValueError( utils.mapping(_("Formula must be a "\
-                  "string ($1)"), (str(formula),)) )
+        if not isinstance(formula, text_type):
+            _tuni = _("Formula must be a text string ($1)")
+            _uni = utils.mapping(_tuni, (formula,))
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         if re.match(".*[^0123456789\.()\+\-\*/\^abcdp ].*", formula):
-            raise ValueError( utils.mapping(_("There is invalid characters"\
-                  "in formula ($1)"), (str(formula),)) )
+            _tuni = _("There is invalid characters in formula ($1)")
+            _uni =  utils.mapping(_tuni, (formula,))
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         self.__formula = formula
         try:
             self.calculateParcial(decimals)
@@ -1561,19 +1656,27 @@
         try:
             a = float(a)
         except:
-            raise ValueError( _("'a' value must be a float number") )
+            _tuni = _("'a' value must be a float number")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         try:
             b = float(b)
         except:
-            raise ValueError( _("'b' value must be a float number") )
+            _tuni = _("'b' value must be a float number")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         try:
             c = float(c)
         except:
-            raise ValueError( _("'c' value must be a float number") )
+            _tuni = _("'c' value must be a float number")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         try:
             d = float(d)
         except:
-            raise ValueError( _("'d' value must be a float number") )
+            _tuni = _("'d' value must be a float number")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         # spaces are erased
         formula.replace(" ","")
         # operators and varibles are replaced
@@ -1584,16 +1687,16 @@
         formula = formula.replace("^", " ** ")
         formula = formula.replace("(", " ( ")
         formula = formula.replace(")", " ) ")
-        formula = formula.replace("a", str(a))
-        formula = formula.replace("b", str(b))
-        formula = formula.replace("c", str(c))
-        formula = formula.replace("d", str(d))
+        formula = formula.replace("a", text(a))
+        formula = formula.replace("b", text(b))
+        formula = formula.replace("c", text(c))
+        formula = formula.replace("d", text(d))
         formula = formula.replace("p", "3.1415926")
         _list_formula = formula.split(" ")
         _formula2 = ""
         for oper in _list_formula:
             try:
-                _float_oper= str(float(oper))
+                _float_oper= text(float(oper))
                 _formula2 = _formula2 + _float_oper
             except ValueError:
                 _formula2 = _formula2 + oper
@@ -1601,7 +1704,9 @@
         try:
             return eval(_formula2, _g)
         except:
-            raise ValueError( _("Invalid formula") )
+            _tuni = _("Invalid formula")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
 
 
 class Decimals(object):
@@ -1855,7 +1960,9 @@
 
     def setSheet_dict(self, sheet_dict):
         if not isinstance(sheet_dict, dict):
-            raise ValueError( _("sheet_dict must be a dictionay") )
+            _tuni = _("sheet_dict must be a dictionay")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         self.__sheet_dict = sheet_dict
 
     def getFields(self):
@@ -1875,19 +1982,29 @@
             return None
 
     def addField(self, field, section_dict):
-        if not isinstance(field, str):
-            raise ValueError( _("sheet field must be a string") )
+        if not isinstance(field, text_type):
+            _tuni = _("sheet field must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         if not isinstance(section_dict, dict):
-            raise ValueError( _("section_dict must be a dictionary") )
+            _tuni = _("section_dict must be a dictionary")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         self.__sheet_dict[field] = section_dict
 
     def addSection(self, field, section, paragraph):
-        if not isinstance(field, str):
-            raise ValueError( _("sheet field must be a string") )
-        if not isinstance(section, str):
-            raise ValueError( _("sheet section must be a string") )
-        if not isinstance(paragraph, str):
-            raise ValueError( _("sheet paragraph must be a string") )
+        if not isinstance(field, text_type):
+            _tuni = _("sheet field must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
+        if not isinstance(section, text_type):
+            _tuni = _("sheet section must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
+        if not isinstance(paragraph, text_type):
+            _tuni = _("sheet paragraph must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         if not field in self.__sheet_dict:
             self.addField(field, { })
         _field = self.__sheet_dict[field]
@@ -2172,10 +2289,12 @@
         owner: data owner 
         Set the data owner.
         """
-        if isinstance(owner, basestring):
+        if isinstance(owner, text_type):
             self.__file_owner = owner
         else:
-            raise  TypeError( _("Owner must be a string") )
+            _tuni = _("Owner must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise  TypeError(_str)
 
     def setDate(self, date):
         """setOwner(self, date)
@@ -2191,7 +2310,10 @@
                 datetime.date(*date)
             self.__date = date
         else:
-            raise  TypeError(utils.mapping(_("Invalid Date: $1"),(str(date),)))
+            _tuni = _("Invalid Date: $1")
+            _uni = utils.mapping(_tuni,(text(date),))
+            _str = _uni.encode("utf-8")
+            raise  TypeError(_str)
 
     def setComment(self, comment):
         """setOwner(self, comment)
@@ -2199,10 +2321,12 @@
         comment: text to comment the budged
         Set the comment.
         """
-        if isinstance(comment, basestring):
+        if isinstance(comment, text_type):
             self.__comment = comment
         else:
-            raise  TypeError( _("Comment must be a string") )
+            _tuni = _("Comment must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise  TypeError(_str)
 
     def setBudgeType(self, budget_type):
         """setOwner(self, budget_type)
@@ -2218,7 +2342,9 @@
         if budget_type in [1, 2, 3, 4]:
             self.__budgetType = budget_type
         else:
-            raise  ValueError( _("Budget type must be 1, 2, 3 or 4.") )
+            _tuni = _("Budget type must be 1, 2, 3 or 4.")
+            _str = _tuni.encode("utf-8")
+            raise  ValueError(_str)
 
     def setCertificateOrder(self, certificate_order, certificate_date):
         """setOwner(self, budget_type)
@@ -2230,7 +2356,9 @@
         if isinstance(certificate_order, int):
             self.__budgetCerficateOrder = certificate_order
         else:
-            raise  ValueError( _("Certificate order must be a integer.") )
+            _tuni =  _("Certificate order must be a integer.")
+            _str = _tuni.encode("utf-8")
+            raise  ValueError(_str)
 
     def setCertificateDater(self, certificate_date):
         """setCertidicateDate(self, certificate_date)
@@ -2245,7 +2373,8 @@
             datetime.date(*certificate_date)
             self.__budgetCerficateDate = certificate_date
         else:
-            _str = _("Budget certificate Date must be a valid Date.")
+            _tuni = _("Budget certificate Date must be a valid Date.")
+            _str = _tuni.encode("utf-8")
             raise  ValueError(_str)
 
     def setTitleList(self, title_list):
@@ -2254,13 +2383,15 @@
         title_list: [ "Header", ["Title1", "Title2", ... ] ]
         Set the header and titles for the price groups and decimals.
         """
-        title_list[0] = str(title_list[0])
+        title_list[0] = text(title_list[0])
         if isinstance(title_list, list) and isinstance(title_list[1], list):
             for i in range(len(title_list[1])):
-                title_list[1][i] = str(title_list[1][i])
+                title_list[1][i] = text(title_list[1][i])
             self.__title_list = title_list
         else:
-            raise TypeError( _("Invalid title list format") )
+            _tuni = _("Invalid title list format")
+            _str = _tuni.encode("utf-8")
+            raise TypeError(_str)
 
     def getTitleList(self):
         """ getTitleList(self)
@@ -2289,7 +2420,9 @@
         elif N < len(self.__decimals):
             _default_decimals = self.__decimals[N]
         else:
-            raise IndexError( _("Invalid Index Title") )
+            _tuni = _("Invalid Index Title")
+            _str = _tuni.encode("utf-8")
+            raise IndexError(_str)
         for _decimal in dictionary:
             if dictionary[_decimal] == "":
                 dictionary[_decimal] = eval("_default_decimals." + _decimal)
@@ -2364,7 +2497,9 @@
         elif key in self.__percentages:
             return self.__percentages[key]
         else:
-            raise KeyError( _("Invalid Percentage key") )
+            _tuni = _("Invalid Percentage key")
+            _str = _tuni.encode("utf-8")
+            raise KeyError(_str)
 
     def getAllParents(self,code):
         """getAllParents(self,code)
@@ -2435,15 +2570,13 @@
         return _measure
 
     def getStrYield(self, measure, recordType):
-        #_DR = measure.getDR(self.getDecimals())
         _DR = abs(self.getDecimals().getDR(recordType))
-        _yield = ("%." + str(_DR) + "f" ) % measure.yield_
+        _yield = ("%." + text(_DR) + "f" ) % measure.yield_
         return _yield
 
     def getStrFactor(self, measure, recorType):
         _DF = abs(self.getDecimals().getDF(recordType))
-        #_DF = measure.getDF(self.getDecimals())
-        _factor = ("%." + str(_DF) + "f" ) % measure.factor
+        _factor = ("%." + text(_DF) + "f" ) % measure.factor
         return _factor
 
     def setTree(self, code, child_code, position, factor, yield_, total,
@@ -2481,30 +2614,37 @@
         if code is None: # No-estructured measures
             code = self.getRoot()
             if code == None: # No root
-                print( "No-estructured measures. Adding root record " +  
-                str(self.setRecord("root", [], 0, "", "", [0.0,], [(1,1,1970)],
-                                     0, "") ).encode("utf8"))
+                _record = self.setRecord("root", [], 0, "", "", [0.0,],
+                                         [(1,1,1970)], 0, "")
+                _tuni = _("No-estructured measures. Adding root record")
+                print(_tuni)
                 code = self.getRoot()
 
         if not utils.is_valid_code(code)[0]:
-            raise ValueError( utils.mapping(_("Invalid parent code: $1"),
-                                            (str(code),)) )
+            _tuni = _("Invalid parent code: $1")
+            _uni = utils.mapping(_tuni, (code,))
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         if not utils.is_valid_code(child_code)[0]:
-            raise ValueError( utils.mapping(_("Invalid child code: $1 $2"),
-                                           (str(code),str(child_code))) )
+            _tuni = _("Invalid child code: $1 $2")
+            _uni = utils.mapping(_tuni, (code,child_code))
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         if not isinstance(position, int):
-            raise ValueError( utils.mapping(_("Invalid position in measure "\
-                  "$1, in code $2"), (str(parent_code), str(position))) )
+            _tuni = _("Invalid position in measure $1, in code $2 $3")
+            _uni = utils.mapping(_tuni, (text(position), code, child_code))
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         # Test circular references
         _all_parent_list = self.getAllParents(code) + [ code ]
         _all_child_list = self.getAllchildren(child_code) + [ child_code ]
         for _parent_code in _all_parent_list:
             if _parent_code in _all_child_list:
                 # TODO: change return to except
-                _str = _("Circular Decomposition, parent code: "\
+                _tuni = _("Circular Decomposition, parent code: "\
                          "$1, child code: $2, repeated code: $3")
-                print(utils.mapping(_str, (str(code), str(child_code),
-                                           str(_parent_code))).encode("utf8") )
+                _uni = utils.mapping(_tuni, (code, child_code, _parent_code))
+                print(_uni)
                 return
 
         # Creating reference to parent code in child record
@@ -2528,19 +2668,21 @@
                 positions = _record.getChildPositions(child_code)
                 if len(positions) == 1:
                     position = positions[0]
-                    _str = _("No-estructured measure or empty position. " \
+                    _tuni = _("No-estructured measure or empty position. " \
                              "Parent Code: $1, Child code: $2, Position: $3")
-                    print(utils.mapping(_str,(str(code), str(child_code),
-                                        str(position))).encode("utf8") )
+                    _uni = utils.mapping(_tuni,(code, child_code,
+                                         text(position)))
+                    print(_uni)
                 else:
                     position = _child_number
-                    _str = _("No-estructured measure or empty position. "\
+                    _tuni = _("No-estructured measure or empty position. "\
                              "Repeated child in unspecified position. "\
                              "It is impossible to determine the position. "\
                              "New child is added in the decomposition. "\
                              "Parent code: $1, Child code: $2, Position: $3")
-                    print(utils.mapping(_str,(str(code), str(child_code),
-                                        str(position))).encode("utf8") )
+                    _uni = utils.mapping(_tuni,(code, child_code,
+                                         text(position)))
+                    print(_uni)
             if position == _child_number:
                 # The record do not have the child
                 if not isinstance(factor, float): factor = 1.0
@@ -2572,31 +2714,33 @@
                 if isinstance(list_lines, list) and len(list_lines) > 0:
                     _measure.buildMeasure(list_lines, type_, self.getDecimals(),
                                           _record.recordType)
-                if isinstance(label, str) and label != "" :
+                if isinstance(label, text_type) and label != "" :
                     _measure.label = label
             else:
                 # TODO: change return for except
-                _str = _("Error: Invalid child position in "
+                _tuni = _("Error: Invalid child position in "
                          "decomposition. Parent code: $1 Child code: $2 "\
                          "Position: $3")
-                print(utils.mapping(_str, (str(code), str(child_code),
-                                    str(position))).encode("utf8") )
+                _uni = utils.mapping(_tuni, (code, child_code,
+                                     text(position)))
+                print(_uni)
                 return
         else:
             if child_code == "" :
-                _str = _("Error: Empty child code. Parent code: "\
+                _tuni = _("Error: Empty child code. Parent code: "\
                          "$1 Position: $2")
-                print(utils.mapping(_str, (str(code),
-                                           str(position))).encode("utf8") )
+                _uni = utils.mapping(_tuni, (code, text(position)))
+                print(_uni)
                 return
             if position == -1:
                 position = 0
             elif position != 0:
-                _str = _("Error: Invalid child position in "\
+                _tuni = _("Error: Invalid child position in "\
                          "decomposition. Parent code: $1 Child code: $2 "\
                          "Position: $3")
-                print(utils.mapping(_str, (str(code), str(child_code),
-                                    str(position))).encode("utf8") )
+                _uni = utils.mapping(_tuni, (code, child_code, 
+                                             text(position)))
+                print(_uni)
                 return
             if not isinstance(factor, float):
                 factor = 1.0
@@ -2629,19 +2773,27 @@
         try:
             a = float(a)
         except:
-            raise ValueError( _("'a' value must be a float number") )
+            _tuni = _("'a' value must be a float number")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         try:
             b = float(b)
         except:
-            raise ValueError( _("'b' value must be a float number") )
+            _tuni = _("'b' value must be a float number")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         try:
             c = float(c)
         except:
-            raise ValueError( _("'c' value must be a float number") )
+            _tuni = _("'c' value must be a float number")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         try:
             d = float(d)
         except:
-            raise ValueError( _("'d' value must be a float number") )
+            _tuni = _("'d' value must be a float number")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         # spaces are erased
         sre.sub("[ ]","",formula)
         # operators and varibles are replaced
@@ -2652,16 +2804,16 @@
         formula = formula.replace("^", " ** ")
         formula = formula.replace("(", " ( ")
         formula = formula.replace(")", " ) ")
-        formula = formula.replace("a", str(a))
-        formula = formula.replace("b", str(b))
-        formula = formula.replace("c", str(c))
-        formula = formula.replace("d", str(d))
+        formula = formula.replace("a", text(a))
+        formula = formula.replace("b", text(b))
+        formula = formula.replace("c", text(c))
+        formula = formula.replace("d", text(d))
         formula = formula.replace("p", "3.1415926")
         _list_formula = formula.split(" ")
         _formula2 = ""
         for oper in _list_formula:
             try:
-                _float_oper= str(float(oper))
+                _float_oper= text(float(oper))
                 _formula2 = _formula2 + _float_oper
             except ValueError:
                 _formula2 = _formula2 + oper
@@ -2669,7 +2821,9 @@
         try:
             return eval(_formula2, _g)
         except:
-            raise ValueError( _("Invalid formula") )
+            _tuni = _("Invalid formula")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
 
     def getText(self,code):
         """getText(self,code)
@@ -2680,7 +2834,9 @@
         if code in self.__records:
             return self.__records[code].text
         else:
-            raise IndexError( _("Invalid code") )
+            _tuni = _("Invalid code")
+            _str = _tuni.encode("utf-8")
+            raise IndexError(_str)
 
     def setText(self,code,text):
         """setText(self,code,text)
@@ -2690,8 +2846,10 @@
         Sests the description text of a record
         """
         if not utils.is_valid_code(code)[0]:
-            _str = _("Invalid record: $1")
-            raise ValueError( utils.mapping(_str, (str(code),)) )
+            _tuni = _("Invalid record: $1")
+            _uni = utils.mapping(_tuni, (code,))
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         if not code in self.__records:
             _record = self.setRecord(code, [], "", "", "", [], [],
                                      "", "")
@@ -2754,7 +2912,8 @@
             if self.__root is None:
                 self.__root = code
             else:
-                print(_("Only can be one root record").encode("utf8") )
+                _tuni = _("Only can be one root record")
+                print(_tuni)
                 return
                 # TODO: If the root is created in settree.
                 #       No-estructured measures
@@ -2845,7 +3004,7 @@
         else:
             _price = record.getPrice(index_price)
         _D = abs(self.getDecimals().getD(record.recordType))
-        _price = ("%." + str(_D) + "f" ) % _price
+        _price = ("%." + text(_D) + "f" ) % _price
         return _price
 
     def getCode(self, path):
@@ -2864,16 +3023,24 @@
                         try:
                             _child = _children_list[i]
                         except:
-                            raise ValueError( _("This record does not exits") )
+                            _tuni = _("This record does not exits")
+                            _str = _tuni.encode("utf-8")
+                            raise ValueError(_str)
                         _code = _child.code
                     else:
-                        raise ValueError( _("Path item must be a integer") )
+                        _tuni = _("Path item must be a integer")
+                        _str = _tuni.encode("utf-8")
+                        raise ValueError(_str)
                 return _code
             else:
-                raise ValueError( _("This record does not exits") )
+                _tuni = _("This record does not exits")
+                _str = _tuni.encode("utf-8")
+                raise ValueError(_str)
         else:
-            raise ValueError( utils.mapping(_("Path must be a not empty "\
-                  "tuple: $1"), (str(path),)) )
+            _tuni = _("Path must be a not empty tuple: $1")
+            _uni = utils.mapping(_tuni, (text(path),))
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
 
     def getAmount(self, path):
         """def getAmount(self,path)
@@ -2891,7 +3058,6 @@
             _parent_code = self.getCode(path[:-1])
             _parent_record = self.getRecord(_parent_code)
             _child_number = path[-1]
-            
             _decomposition = _parent_record.children[_child_number]
             _factor = _decomposition.budgetMeasures[0].factor
             _yield = _decomposition.budgetMeasures[0].yield_
@@ -2934,14 +3100,18 @@
             _parent_record = self.getRecord(_parent_code)
             _amount = self.getAmount(path)
             _DI = abs(self.getDecimals().getDI(_parent_record.recordType))
-            _amount = ("%." + str(_DI) + "f") % _amount
+            _amount = ("%." + text(_DI) + "f") % _amount
             return _amount
 
     def setSheetSection(self,sheet_code,sheet_title):
-        if not isinstance(sheet_code, str):
-            raise ValueError( _("The sheet code must be a string") )
-        if not isinstance(sheet_title, str):
-            raise ValueError( _("The sheet title must be a string") )
+        if not isinstance(sheet_code, text_type):
+            _tuni = _("The sheet code must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
+        if not isinstance(sheet_title, text_type):
+            _tuni = _("The sheet title must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         self.__sheet_sections[sheet_code] = sheet_title
 
     def hasSheetSection(self, section):
@@ -2952,15 +3122,21 @@
 
     def setSheetSections(self,dictionary): 
         if not isinstance(dictionary, dict):
-            raise ValueError( _("The sheet sections must be a dictionary") )
+            _tuni = _("The sheet sections must be a dictionary")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         for sheet_code in dictionary.keys():
             self.setSheetSection(sheet_code, dictionary[sheet_code])
 
     def setSheetField(self, field_code, field_title):
-        if not isinstance(field_code, str):
-            raise ValueError( _("The field code must be a string") )
-        if not isinstance(field_title, str):
-            raise ValueError( _("The field title must be a string") )
+        if not isinstance(field_code, text_type):
+            _tuni = _("The field code must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
+        if not isinstance(field_title, text_type):
+            _tuni = _("The field title must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         self.__sheet_fields[field_code] = field_title
 
     def hasSheetField(self, field):
@@ -2971,15 +3147,21 @@
 
     def setSheetFields(self, field_dict):
         if not isinstance(field_dict, dict):
-            raise ValueError( _("The sheet field must be a dictionary") )
+            _tuni = _("The sheet field must be a dictionary")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         for field_code in field_dict.keys():
             self.setSheetField( field_code, field_dict[field_code])
 
     def setSheetParagraph(self, paragraph_code, paragraph_text):
-        if not isinstance(paragraph_code, str):
-            raise ValueError( _("The paragraph code must be a string") )
-        if not isinstance(paragraph_text, str):
-            raise ValueError( _("The paragraph text must be a string") )
+        if not isinstance(paragraph_code, text_type):
+            _tuni = _("The paragraph code must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
+        if not isinstance(paragraph_text, text_type):
+            _tuni = _("The paragraph text must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         self.__sheet_paragraphs[paragraph_code] = paragraph_text
 
     def hasSheetParagraph(self, paragraph):
@@ -2990,31 +3172,39 @@
 
     def setSheetParagraphs(self, paragraph_dict):
         if not isinstance(paragraph_dict, dict):
-            raise ValueError( _("The paragraph dict must be a dictionary") )
+            _tuni = _("The paragraph dict must be a dictionary")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         for paragraph_code in paragraph_dict.keys():
             self.setSheetParagraph(paragraph_code,
                                    paragraph_dict[paragraph_code])
 
     def setSheetRecord(self, record_code, field, section_dict):
-        if not isinstance(record_code, str):
-            raise ValueError( _("The record_code code must be a string") )
-        if not isinstance(field, str):
-            raise ValueError( _("The field must be a string") )
+        if not isinstance(record_code, text_type):
+            _tuni = _("The record_code code must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
+        if not isinstance(field, text_type):
+            _tuni = _("The field must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         if not isinstance(section_dict, dict):
-            raise ValueError( _("The section dict must be a dictionary") )
+            _tuni = _("The section dict must be a dictionary")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         #-#
         # TODO: Add a empty record?
         if not self.hasRecord(record_code):
-            _str = _("Error: The budget do not have this record "\
+            _tuni = _("Error: The budget do not have this record "\
                    "code and can not be added the sheet text in the field $1. "\
                    "Record Code: $2")
-            print(utils.mapping(_str, ( str(field),
-                                str(record_code))).encode("utf8") )
+            _uni = utils.mapping(_tuni, ( text(field), record_code))
+            print(_uni)
             return
         #-#
         if not self.hasSheetField(field):
             self.setSheetField(field, "")
-        for section, paragraph in section_dict.iteritems():
+        for (section, paragraph) in section_dict.items():
             if not self.hasSheetParagraph(paragraph):
                 self.setSheetParagraph(paragraph,"")
             if not self.hasSheetSection(section):
@@ -3023,46 +3213,62 @@
             _sheet.addSection(field, section, paragraph)
 
     def addFile(self, record_code, filepath, type_, description):
-        if not isinstance(record_code, str):
-            raise ValueError( _("The record_code code must be a string") )
-        #-# str and unicode
-        if not isinstance(filepath, str) and not isinstance(filepath, unicode):
-            raise ValueError( _("The filename must be a string") )
-        #-#
+        if not isinstance(record_code, text_type):
+            _tuni = _("The record_code code must be a text string")
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
+        if not isinstance(filepath, text_type):
+            _tuni = _("The filename must be a text string")
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         # TODO: Add a empty record?
         if not self.hasRecord(record_code):
-            print(utils.mapping(_("Error: The budget do not have the record "\
-                "code $1 and can not be added the file: $2"),
-                (str(record_code), str(filepath))).encode("utf8") )
+            _tuni = _("Error: The budget do not have the record "\
+                      "code $1 and can not be added the file: $2")
+            _uni = utils.mapping(_tuni, (record_code, filepath))
+            print(_uni)
             return
-        #-#
         _record = self.getRecord(record_code)
         _record.addFile(filepath, type_, description)
 
     def setCompany(self, company_code, sumamary, name, offices,
                    cif, web, email):
-        if not isinstance(company_code, str):
-            raise ValueError( _("The company code must be a string") )
-        if not isinstance(sumamary, str):
-            raise ValueError( _("The summary must be a string") )
-        if not isinstance(name, str):
-            raise ValueError( _("The name must be a string") )
+        if not isinstance(company_code, text_type):
+            _tuni = _("The company code must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
+        if not isinstance(sumamary, text_type):
+            _tuni = ("The summary must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
+        if not isinstance(name, text_type):
+            _tuni = _("The name must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         if not isinstance(offices, list):
-            raise ValueError( _("The name must be a list") )
+            _tuni = _("The name must be a list")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         _offices = []
         for _office in offices:
             if not isinstance(_office, list):
-                raise ValueError( _("The office must be a list") )
+                _tuni = _("The office must be a list")
+                _str = _tuni.encode("utf-8")
+                raise ValueError(_str)
             if not len(_office) == 10:
-                raise ValueError( _("The office must be a 10 items list") )
+                _tuni = _("The office must be a 10 items list")
+                _str = _tuni.encode("utf-8")
+                raise ValueError(_str)
             for _item in _office[:7] + _office[9:10]:
-                if not isinstance(_item, str):
-                    raise ValueError( _("This office item must be a "\
-                                        "string") )
+                if not isinstance(_item, text_type):
+                    _tuni = _("This office item must be a text string")
+                    _str = _tuni.encode("utf-8")
+                    raise ValueError(_str)
             for _item in _office[7:8]:
                 if not isinstance(_item, list):
-                    raise ValueError( _("This office item must be a "\
-                                        "list") )
+                    _tuni = _("This office item must be a list")
+                    _str = _tuni.encode("utf-8")
+                    raise ValueError(_str)
             _offices.append(Office(_office[0],
                                   _office[1],
                                   _office[2],
@@ -3073,12 +3279,18 @@
                                   _office[7],
                                   _office[8],
                                   _office[9]))
-        if not isinstance(cif, str):
-            raise ValueError( _("The name must be a string") )
-        if not isinstance(web, str):
-            raise ValueError( _("The web must be a string") )
-        if not isinstance(email, str):
-            raise ValueError( _("The email must be a string") )
+        if not isinstance(cif, text_type):
+            _tuni = _("The name must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
+        if not isinstance(web, text_type):
+            _tuni = _("The web must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
+        if not isinstance(email, text_type):
+            _tuni = _("The email must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         
         self.__companys[company_code] = Company(company_code, sumamary, name,
                                                 _offices, cif, web, email)
@@ -3089,13 +3301,18 @@
         return self.__companys.keys()
 
     def addTecInfo(self, ti_code, text, unit):
-        if not isinstance(ti_code, str):
-            raise ValueError( _("The tecnical info code must be a string") )
-        if not isinstance(text, str):
-            raise ValueError( _("The tecnical info description must be a "\
-                                "string") )
-        if not isinstance(unit, str):
-            raise ValueError( _("The tecnical info unit must be a string") )
+        if not isinstance(ti_code, text_type):
+            _tuni = _("The tecnical info code must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
+        if not isinstance(text, text_type):
+            _tuni = _("The tecnical info description must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
+        if not isinstance(unit, text_type):
+            _tuni = _("The tecnical info unit must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         self.__tec_info[ti_code] = [text, unit]
 
     def hasTecInfo(self, ti_code):
@@ -3145,8 +3362,10 @@
         
         Add a label to a record
         """
-        if not isinstance(label,str):
-            raise ValueError( _("The label must be a string") )
+        if not isinstance(label, text_type):
+            _tuni = _("The label must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         if self.hasRecord(record_code):
             _record = self.__records[record_code]
             _record.addLabel(label)
@@ -3162,22 +3381,27 @@
         
         Sets Paramtric Record Select Comment
         """
-        if not isinstance(record_code, str):
-            raise ValueError( _("The record_code code must be a string") )
-        if not isinstance(comment, str):
-            raise ValueError( _("The parametric select comment must be a "\
-                                "string") )
+        if not isinstance(record_code, text_type):
+            _tuni = _("The record_code code must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
+        if not isinstance(comment, text_type):
+            _tuni = _("The parametric select comment must be a text string")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         if not self.hasRecord(record_code):
-            print(utils.mapping(_("Error: The budget do not have the record "\
-                "code $1 and can not be added the Parametric select comment: "\
-                "$2"),
-                (str(record_code), str(comment))).encode("utf8") )
+            _tuni = _("Error: The budget do not have the record "\
+                      "code $1 and can not be added the Parametric "\
+                      "select comment: $2")
+            _uni = utils.mapping(_tuni, (record_code, comment))
+            print(_uni)
             return
         _record = self.getRecord(record_code)
         if not isinstance(_record, ParametricRecord):
-            print(utils.mapping(_("Error: The Record $1 is not a "\
-                "Parametric Record and can not have Parametric comment"),
-                (str(record_code),)).encode("utf8") )
+            _tuni = _("Error: The Record $1 is not a "\
+                      "Parametric Record and can not have Parametric comment")
+            _uni = utils.mapping(_tuni, (record_code,))
+            print(_uni)
         else:
             _record.select_comment = comment
 
@@ -3186,20 +3410,26 @@
         
         Sets parametric record summary
         """
-        if not isinstance(record_code, str):
-            raise ValueError( _("The record_code code must be a string") )
-        if not isinstance(summary, str):
-            raise ValueError( _("The summary record must be a string") )
+        if not isinstance(record_code, text_type):
+            _tuni = _("The record_code code must be a text string")
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
+        if not isinstance(summary, text_type):
+            _tuni = _("The summary record must be a text string")
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         if not self.hasRecord(record_code):
-            print(utils.mapping(_("Error: The budget do not have the record "\
-                "code $1 and can not be seted the summary: $2"),
-                (str(record_code), str(summary))).encode("utf8") )
+            _tuni = _("Error: The budget do not have the record "\
+                      "code $1 and can not be seted the summary: $2")
+            _uni = utils.mapping(_tuni, (record_code, summary))
+            print(_uni)
             return
         _record = self.getRecord(record_code)
         if not isinstance(_record, ParametricRecord):
-            print(utils.mapping(_("Error: The Record $1 is not a "\
-                "Parametric Record and can not have Parametric summary"),
-                (str(record_code),)).encode("utf8") )
+            _tuni = _("Error: The Record $1 is not a "\
+                      "Parametric Record and can not have Parametric summary")
+            _uni = utils.mapping(_tuni, (record_code,))
+            print(_uni)
         else:
             self.getRecord(record_code).parametric_summary = summary
 
@@ -3208,20 +3438,26 @@
         
         Sets parametric record text
         """
-        if not isinstance(record_code, str):
-            raise ValueError( _("The record_code code must be a string") )
-        if not isinstance(text, str):
-            raise ValueError( _("The text record must be a string") )
+        if not isinstance(record_code, text_type):
+            _tuni = _("The record_code code must be a text string")
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
+        if not isinstance(text, text_type):
+            _tuni = _("The text record must be a text string")
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         if not self.hasRecord(record_code):
-            print(utils.mapping(_("Error: The budget do not have the record "\
-                "code $1 and can not be seted the text: $2"),
-                (str(record_code), str(text))).encode("utf8") )
+            _tuni = _("Error: The budget do not have the record "\
+                      "code $1 and can not be seted the text: $2")
+            _uni = utils.mapping(_tuni, (record_code, text))
+            print(_uni)
             return
         _record = self.getRecord(record_code)
         if not isinstance(_record, ParametricRecord):
-            print(utils.mapping(_("Error: The Record $1 is not a "\
-                "Parametric Record and can not have Parametric text"),
-                (str(record_code),)).encode("utf8") )
+            _tuni = _("Error: The Record $1 is not a "\
+                      "Parametric Record and can not have Parametric text")
+            _uni = utils.mapping(_tuni, (record_code,))
+            print(_uni)
         else:
             self.getRecord(record_code).parametric_text = text
 
@@ -3742,10 +3978,14 @@
 
     def setHierarchy(self, hierarchy):
         if not hierarchy in [-1, 0 , 1 ,2, ""]:
-            raise ValueError( utils.mapping(_("Invalid Hierarchy ($1) "\
-                  "The hierarchy must be -1, 0, 1, 2"), (str(hierarchy),)) )
+            _tuni = _("Invalid Hierarchy ($1) "\
+                      "The hierarchy must be -1, 0, 1, 2")
+            _uni = utils.mapping(_tuni, (text(hierarchy),))
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         elif hierarchy == "":
-            print("Hierarchy temporarily set to an empty string".encode("utf8"))
+            _tuni = _("Hierarchy temporarily set to an empty string")
+            print(_tuni)
         #TODO Check empty Hierarchy in Generic.fiebdc.Read._testBudget
         self.__hierarchy = hierarchy
 
@@ -3753,9 +3993,12 @@
         return self.__type
 
     def setType(self, type_):
-        if not type_ in  ["", 0, 1, 2, 3] :
-            raise ValueError( utils.mapping(_("Invalid type ($1),"\
-                  "the type must be (empty string,0,1,2,3)"),(str(type_)),) )
+        if not type_ in  ["", 0, 1, 2, 3]:
+            _tuni = _("Invalid type ($1),"\
+                      "the type must be (empty string,0,1,2,3)")
+            _uni = utils.mapping(_tuni ,(text(type_),))
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         self.__type = type_
 
     def getSubtype(self):
@@ -3765,10 +4008,13 @@
         if not subtype in ["", "OB", "PU", "EA", "EU", "EC", "EF", "PA", "H",
                            "Q", "%", "MC", "MCr", "MM", "MS", "ME", "MCu",
                            "Mal","ML","M"]:
-            raise ValueError( utils.mapping(_("Invalid subtype ($1), The "\
+            _tuni = _("Invalid subtype ($1), The "\
                   "subtype must one in (empty string, EA, "\
                   "EU, EC, EF, OB, PA, PU, H, Q, %, MC, MCr, "\
-                  "MM, MS, ME, MCu, MAl, ML, M)"), (str(subtype),)) )
+                  "MM, MS, ME, MCu, MAl, ML, M)")
+            _uni = utils.mapping(_tuni, (text(subtype),))
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         self.__subtype = subtype
 
     hierarchy = property(getHierarchy, setHierarchy, None,
--- a/Generic/fiebdc.py	Mon May 20 13:18:33 2019 +0200
+++ b/Generic/fiebdc.py	Tue Jun 18 17:50:23 2019 +0200
@@ -22,6 +22,13 @@
 # specifications in http://www.fiebdc.org
 
 # Modules
+
+# python 2/3 compatibility
+from __future__ import absolute_import, division, print_function, unicode_literals
+from builtins import str as text
+from six import text_type
+from io import open
+
 import time
 import re
 import calendar
@@ -29,7 +36,6 @@
 import unicodedata
 import hashlib
 # pyArq-Presupuestos modules
-import base
 from Generic import utils
 from Generic import globalVars
 
@@ -93,26 +99,26 @@
                                       "437" : "cp437"}
         self.__file_format = "FIEBDC-3/2007"
         self.__generator = globalVars.name + " " + globalVars.version
-        self.__character_set = "850"
+        self.__character_set = "850" # ¿set default character set to cp1252?
         self.__pattern = {
-            "control_tilde" : re.compile(u"((\r\n)| |\t)+~"),
-            "control_vbar" : re.compile(u"((\r\n)| |\t)+\|"),
-            "control_backslash" : re.compile(ur"((\r\n)| |\t)+\\"),
-            "valid_code" : re.compile(u"[^A-Za-z0-9ñÑ.$#%&_]"),
-            "special_char": re.compile(u"[#%&]"),
-            "no_float": re.compile(u"[^\-0-9.]"),
-            "formula" : re.compile(u".*[^0123456789\.()\+\-\*/\^abcdp ].*"),
-            "comment": re.compile(u"#.*\r\n"),
-            "empty_line": re.compile(ur"(\r\n) *\r\n"),
-            "space_before_backslash" : re.compile(ur"( )+\\"),
-            "space_after_backslash" : re.compile(ur"\\( )+"),
-            "start_noend_backslash" : re.compile(u"(\r\n\\\.*[^\\\])\r\n"),
-            "end_oper": re.compile(u"(\+|-|\*|/|/^|@|&|<|>|<=|>=|=|!) *\r\n"),
-            "matricial_var" : re.compile(u"(\r\n *[%|\$][A-ZÑ].*=.*,) *\r\n"),
-            "descomposition" : re.compile(u"^([^:]+):(.*)$"),
-            "var" : re.compile(u"^([$%][A-ZÑ][()0-9, ]*)=(.*)$"),
-            "after_first_tilde" : re.compile(u"^[^~]*~"),
-            "end_control" : re.compile(u"((\r\n)| |\t)+$"),
+            "control_tilde" : re.compile("((\r\n)| |\t)+~"),
+            "control_vbar" : re.compile("((\r\n)| |\t)+\|"),
+            "control_backslash" : re.compile(r"((\r\n)| |\t)+\\"),
+            "valid_code" : re.compile("[^A-Za-z0-9ñÑ.$#%&_]"),
+            "special_char": re.compile("[#%&]"),
+            "no_float": re.compile("[^\-0-9.]"),
+            "formula" : re.compile(".*[^0123456789\.()\+\-\*/\^abcdp ].*"),
+            "comment": re.compile("#.*\r\n"),
+            "empty_line": re.compile(r"(\r\n) *\r\n"),
+            "space_before_backslash" : re.compile(r"( )+\\"),
+            "space_after_backslash" : re.compile(r"\\( )+"),
+            "start_noend_backslash" : re.compile("(\r\n\\\.*[^\\\])\r\n"),
+            "end_oper": re.compile("(\+|-|\*|/|/^|@|&|<|>|<=|>=|=|!) *\r\n"),
+            "matricial_var" : re.compile("(\r\n *[%|\$][A-ZÑ].*=.*,) *\r\n"),
+            "descomposition" : re.compile("^([^:]+):(.*)$"),
+            "var" : re.compile("^([$%][A-ZÑ][()0-9, ]*)=(.*)$"),
+            "after_first_tilde" : re.compile("^[^~]*~"),
+            "end_control" : re.compile("((\r\n)| |\t)+$"),
             }
         self.__statistics = Statistics()
 
@@ -133,9 +139,9 @@
         record ~P
         """
         # "control_tilde" : "((\r\n)| |\t)+~"
-        string = self.__pattern["control_tilde"].sub(u"~",string)
+        string = self.__pattern["control_tilde"].sub("~",string)
         # "control_vbar" : "((\r\n)| |\t)+\|"
-        string = self.__pattern["control_vbar"].sub(u"|",string)
+        string = self.__pattern["control_vbar"].sub("|",string)
         # "control_backslash" : r"((\r\n)| |\t)+\\"
         #string = self.__pattern["control_backslash"].sub(r"\\",string)
         return string
@@ -146,23 +152,24 @@
         Test if the code have invalid characters and try to erase it,
         if it is posible return a valid code else return a empty string.
         """
-        if not isinstance(code, unicode):
-            _str = _("Invalid code, it must be a unicode string")
-            print(_str.encode("utf-8") )
-            return u""
+        if not isinstance(code, text_type):
+            _tuni = _("Invalid code, it must be a text string")
+            print(_tuni)
+            return ""
         # Valid chararcter: A-Z a-z 0-9 ñ Ñ . $ # % & _ 
         # "valid_code" : "[^A-Za-z0-9ñÑ.$#%&_]"
-        _ucode = self.__pattern["valid_code"].sub(u"_", code)
+        _ucode = self.__pattern["valid_code"].sub("_", code)
         if _ucode != code:
             try:
-                _tstr = _("The code '$1' have invalid characters," \
+                _tuni = _("The code '$1' have invalid characters," \
                          " replaced by '$2'.")
-                print(utils.mapping(_tstr, (code.encode("utf8"),
-                                    _ucode.encode("utf8"))) )
+                _uni = utils.mapping(_tuni, (code, _ucode))
+                print(_uni)
             except:
-                _tstr = _("The code '$1' have invalid characters and can not" \
-                         " be encoded in utf8.")
-                print(utils.mapping(_tstr, (code,)).encode("utf-8") )
+                _tuni = _("The code '$1' have invalid characters and can not" \
+                         " be encoded in utf-8.")
+                _uni = utils.mapping(_tuni, (code,))
+                print(_uni)
             
             if len(_ucode) == 0:
                 _normalize_code = ""
@@ -173,22 +180,22 @@
                 # 'NFD', _ucode) if unicodedata.category(c) != 'Mn'))
                 # from http://www.leccionespracticas.com/uncategorized/
                 #      eliminar-tildes-con-python-solucionado/
-                _ucode = self.__pattern["valid_code"].sub(u"", _normalize_code)
+                _ucode = self.__pattern["valid_code"].sub("", _normalize_code)
                 if len(_ucode) == 0:
                     _hash_code = hashlib.sha256()
                     _hash_code.update(code.encode('utf-8'))
                     _hexdigest_code = _hash_code.hexdigest()
                     _p_valid_code = self.__pattern["valid_code"]
-                    _ucode = _p_valid_code.sub(u"", _hexdigest_code)
+                    _ucode = _p_valid_code.sub("", _hexdigest_code)
             code = _ucode
-        if code == u"##":
+        if code == "##":
             # root code is an empty code : set to ROOT
-            return u"ROOT"
+            return "ROOT"
         # the lasts characters can not be <#> or <##>
         # <##> -> root record in FIEFDC-3
         # <#> -> chapter record in FIEFDC-3
         if len(code) > 0:
-            while code[-1] == u"#":
+            while code[-1] == "#":
                 code = code[:-1]
                 if len(code) == 0:
                     return code
@@ -196,12 +203,12 @@
                 code = code[:20]
             # only one charecter # % or &
             if sum([code.count(c) for c in u'#%&']) > 1:
-                print(utils.mapping(_("The code '$1' contains special "\
-                      "characters repeated."),
-                      (code.encode("utf8"),)).encode("utf-8") )
+                _tuni = _("The code '$1' contains special characters repeated.")
+                _uni = utils.mapping(_tuni, (code,))
+                print(_uni)
                 _i = min([code.find(c) for c in u'#%&'])
                 code = code[:_i+1] + \
-                        self.__pattern["special_char"].sub(u"", code[_i+1:])
+                        self.__pattern["special_char"].sub("", code[_i+1:])
         return code
 
     def parseDate(self, date):
@@ -217,11 +224,11 @@
         or None if the date format is invalid
         """
         # All characters must be numbers, len <= 8 and not empty string
-        if not date.isdigit() or len(date) > 8 or date == u"":
+        if not date.isdigit() or len(date) > 8 or date == "":
             return None
         else:
             if len(date)%2 == 1: # uneven len: add a leading 0
-                date = u"0" + date
+                date = "0" + date
             if len(date) == 8:
                 _d = int(date[:2])
                 _m = int(date[2:4])
@@ -251,86 +258,86 @@
         """parseRecord(record, interface)
         
         record: the record line readed from the file whith the format:
-            type|field|field|subfield\subfield|...
+            type|field|field|subfield\\subfield|...
         [a] nothing or "a"
         {a} zero or more #-#twice#-# "a"
         <a> one or more #-#twice#-# "a"
         Types: V C D Y M N T K L Q J G E X B F A
             V: Property and Version
                 1- [File_Owner]
-                2- Format_Version[\DDMMYYYY]
+                2- Format_Version[\\DDMMYYYY]
                 3- [Program_Generator]
-                4- [Header]\{Title\}
+                4- [Header]\\{Title\\}
                 5- [Chaters_set]
                 6- [Comment]
             C: Record:
-                1- Code{\Code}
+                1- Code{\\Code}
                 2- [Unit]
                 3- [Summary]
-                4- {Price\}
-                5- {Date\}
+                4- {Price\\}
+                5- {Date\\}
                 6- [Type]
             D or Y: DECOMPOSITION or ADD DECOMPOSITION
                 1- Parent Code
-                2- <Child Code\ [Factor]\ [Yield]>
+                2- <Child Code\\ [Factor]\\ [Yield]>
             M or N: MEASURE or ADD MEASURE
-                1- [Parent Code\]Child Code
+                1- [Parent Code\\]Child Code
                 2- {Path\}
                 3- TOTAL MEASURE
-                4- {Type\Comment\Unit\Length\Width\Height\}
+                4- {Type\\Comment\\Unit\\Length\\Width\\Height\\}
                 5- [Label]
             T: Text
                 1- Code
                 2- Description text
             K: Coefficients
-                1- { DN \ DD \ DS \ DR \ DI \ DP \ DC \ DM \ DIVISA \ }
-                2-  CI \ GG \ BI \ BAJA \ IVA
-                3- { DRC \ DC \ DRO \ DFS \ DRS \ DFO \ DUO \ DI \ DES \ DN \
-                  DD \ DS \ DIVISA \ }
+                1- { DN \\ DD \\ DS \\ DR \\ DI \\ DP \\ DC \\ DM \\ DIVISA \\ }
+                2-  CI \\ GG \\ BI \\ BAJA \\ IVA
+                3- { DRC \\ DC \\ DRO \\ DFS \\ DRS \\ DFO \\ DUO \\ DI \\ DES \\ DN \\
+                  DD \\ DS \\ DIVISA \\ }
                 4- [ n ]
             L: Sheet of Conditions 1
                 A) 
                     1- Empty
-                    2- {Section Code\Section Title}
+                    2- {Section Code\\Section Title}
                 B)
                     1- Record Code
-                    2- {Section Code\Section Text}
-                    3- {Section Code\RTF file}
-                    4- {Section Code\HTM file}
+                    2- {Section Code\\Section Text}
+                    3- {Section Code\\RTF file}
+                    4- {Section Code\\HTM file}
             Q: Sheet of Conditions 2
                 1- Record Code
-                2- {Section Code\Paragraph key\{Field key;}\}|
+                2- {Section Code\\Paragraph key\\{Field key;}\\}|
             J: Sheet of Conditions 3
                 1- Paragraph code
                 2- [Paragraph text]
                 3- [RTF file]
                 4- [HTML file]
             G: Grafic info
-                1- <grafic_file.ext\>
+                1- <grafic_file.ext\\>
             E: Company
                 1- company Code
                 2 [ summary ]
                 3- [ name ]
-                4- { [ type ] \ [ subname ] \ [ address ] \ [ postal_code ]
-                  \ [ town ] \ [ province ] \ [ country ] \ { phone; } 
-                  \ { fax; }  \ {contact_person; } \ }
-                5- [ cif ] \ [ web ] \ [ email ] \
+                4- { [ type ] \\ [ subname ] \\ [ address ] \\ [ postal_code ]
+                  \\ [ town ] \\ [ province ] \\ [ country ] \\ { phone; } 
+                  \\ { fax; }  \\ {contact_person; } \\ }
+                5- [ cif ] \\ [ web ] \\ [ email ] \\
             X: Tecnical information
                 A)
                     1- Empty
-                    2- < TI_Code \ TI_Descitption \ TI_Unit >
+                    2- < TI_Code \\ TI_Descitption \\ TI_Unit >
                 B)
                     1- Record_code
-                    2- < TI_Code \ TI_value >
+                    2- < TI_Code \\ TI_value >
             F: #-#Adjunto#-# File
                 1- Record code
-                2- { Type \ { Filenames; } \ [Description] }
+                2- { Type \\ { Filenames; } \\ [Description] }
             B: Change code
                 1- Record Code
                 2- New code
             A: Labels
                 1- Record Code
-                2- <Label\>
+                2- <Label\\>
             interface:
         """
         # TODO:  ~L ~J RTF and HTML files
@@ -338,71 +345,72 @@
         # TODO:  ~P. Registro tipo Descripción Paramétrica.
         # TODO:  ~O. Registro tipo Relación Comercial.
         # TODO: test records
-        _field_list = record.split(u"|")
+        _field_list = record.split("|")
         self.__statistics.records = self.__statistics.records +1
         _budget = self.__budget
-        if _field_list[0] == u"V":
+        if _field_list[0] == "V":
             self.__statistics.V += 1
             self._parseV(_field_list)
-        elif _field_list[0] == u"C":
+        elif _field_list[0] == "C":
             self.__statistics.C += 1
             self._parseC(_field_list, interface)
-        elif _field_list[0] == u"D":
+        elif _field_list[0] == "D":
             self.__statistics.D += 1
             self._parseDY(_field_list, interface)
-        elif _field_list[0] == u"Y":
+        elif _field_list[0] == "Y":
             self.__statistics.Y += 1
             self._parseDY(_field_list, interface)
-        elif _field_list[0] == u"M":
+        elif _field_list[0] == "M":
             self.__statistics.M += 1
             self._parseMN(_field_list)
-        elif _field_list[0] == u"N":
+        elif _field_list[0] == "N":
             self.__statistics.N += 1
             self._parseMN(_field_list)
-        elif _field_list[0] == u"T":
+        elif _field_list[0] == "T":
             self.__statistics.T += 1
             self._parseT(_field_list)
-        elif _field_list[0] == u"K":
+        elif _field_list[0] == "K":
             self.__statistics.K += 1
             self._parseK(_field_list)
-        elif _field_list[0] == u"W":
+        elif _field_list[0] == "W":
             self.__statistics.W += 1
             self._parseW(_field_list)
-        elif _field_list[0] == u"L":
+        elif _field_list[0] == "L":
             self.__statistics.L += 1
             self._parseL(_field_list)
-        elif _field_list[0] == u"Q":
+        elif _field_list[0] == "Q":
             self.__statistics.Q += 1
             self._parseQ(_field_list)
-        elif _field_list[0] == u"J":
+        elif _field_list[0] == "J":
             self.__statistics.J += 1
             self._parseJ(_field_list)
-        elif _field_list[0] == u"G":
+        elif _field_list[0] == "G":
             self.__statistics.G += 1
             self._parseG(_field_list)
-        elif _field_list[0] == u"E":
+        elif _field_list[0] == "E":
             self.__statistics.E += 1
             self._parseE(_field_list)
         elif _field_list[0] == "O":
             self.__statistics.O += 1
-        elif _field_list[0] == u"P":
+        elif _field_list[0] == "P":
             self.__statistics.P += 1
             self._parseP(_field_list)
-        elif _field_list[0] == u"X":
+        elif _field_list[0] == "X":
             self.__statistics.X += 1
             self._parseX(_field_list)
-        elif _field_list[0] == u"B":
+        elif _field_list[0] == "B":
             self.__statistics.B += 1
             self._parseB(_field_list)
-        elif _field_list[0] == u"F":
+        elif _field_list[0] == "F":
             self.__statistics.F += 1
             self._parseF(_field_list)
-        elif _field_list[0] == u"A":
+        elif _field_list[0] == "A":
             self.__statistics.A += 1
             self._parseA(_field_list)
         else:
-            print(utils.mapping(_("FIEBDC. Unknow record: $1"),
-                                  (record[:100],)).encode("utf-8"))
+            _tuni = _("FIEBDC. Unknow record: $1")
+            _uni = utils.mapping(_tuni, (record[:100],))
+            print(_uni)
             self.__statistics.unknow += 1
 
     def _parseV(self, field_list):
@@ -421,12 +429,14 @@
             9- [Date budget certificate]
         """
         if self.__statistics.records != 1:
-            print(utils.mapping(_("The 'V' record (Property and Version) "\
+            _tuni = _("The 'V' record (Property and Version) "\
                     "must be the first record in the file but it is the "\
-                    "number: $1"),
-                    (str(self.__statistics.records),)).encode("utf-8") )
-            print(_("The default values were taken and this V record is "\
-                  "ignored").encode("utf-8") )
+                    "number: $1")
+            _uni = utils.mapping(_tuni, (text(self.__statistics.records),))
+            print(_uni)
+            _tuni = _("The default values were taken and this V record is "\
+                      "ignored")
+            print(_tuni)
             return
         # _____number of fields_____
         # Any INFORMATION after last field separator is ignored
@@ -435,7 +445,7 @@
         # If there are no sufficient fields, the fields are added
         # with empty value:""
         else:
-            field_list = field_list + [u""]*(10-len(field_list))
+            field_list = field_list + [""]*(10-len(field_list))
         # control character are erased: end of line, tab, space
         # only leading and trailing whitespace in owner, generator, comment
         # _____Fields_____
@@ -448,47 +458,47 @@
         _header_title = field_list[4].strip()
         _header_title = self.delete_control(_header_title)
         _character_set = self.delete_control_space(field_list[5])
-        _comment = field_list[6].strip(u"\t \n\r")
+        _comment = field_list[6].strip("\t \n\r")
         _data_type = self.delete_control_space(field_list[7])
         _number_certificate = self.delete_control_space(field_list[8])
         __date_certificate = self.delete_control_space(field_list[9])
         # _____Owner_____
         self.__budget.setOwner(_owner)
         # _____Version-Date_____
-        _version_date = _version_date.split(u"\\")
+        _version_date = _version_date.split("\\")
         _file_format = _version_date[0]
         if _file_format in self.__format_list:
             self.__file_format = _file_format
-            print(utils.mapping(_("FIEBDC format: $1"),
-                                  (_file_format,)).encode("utf-8") )
+            _tuni = _("FIEBDC format: $1")
+            _uni = utils.mapping(_tuni, (_file_format,))
+            print(_uni)
 
         if len(_version_date) > 1:
             _date = _version_date[1]
-            if _date != u"":
+            if _date != "":
                 _parsed_date = self.parseDate(_date)
                 if _parsed_date is not  None:
                     self.__budget.setDate(_parsed_date)
         # _____Generator_____
         # ignored field
-        print(utils.mapping(_("FIEBDC file generated by $1"),
-                            (_generator,)).encode("utf-8") )
+        _tuni = _("FIEBDC file generated by $1")
+        _uni = utils.mapping(_tuni, (_generator,))
+        print(_uni)
         # _____Header_Title_____
-        _header_title = _header_title.split(u"\\")
+        _header_title = _header_title.split("\\")
         _header_title = [_title.strip() for _title in _header_title]
         _header = _header_title.pop(0)
-        _header = [_item.encode("utf8") for _item in _header]
         _title = [ ]
         for _title_index in _header_title:
-            if _title_index != u"":
+            if _title_index != "":
                 _title.append(_title_index)
-        _title = [_item.encode("utf8") for _item in _title]
-        if _header != u"":
+        if _header != "":
             self.__budget.setTitleList([ _header, _title])
         # _____Characters_set_____
         # field parsed in readFile method
         # _____Comment_____
-        if _comment != u"":
-            self.__budget.setComment(_comment.encode("utf8"))
+        if _comment != "":
+            self.__budget.setComment(_comment)
         # _____Data type_____
         # 1 -> Base data.
         # 2 -> Budget.
@@ -547,16 +557,16 @@
         _field1 = self.delete_control_space(field_list[1])
         _field2 = self.delete_control_space(field_list[2])
         # _____Field 1_____
-        if len(_field1) > 0 and _field1[-1] == u"\\":
+        if len(_field1) > 0 and _field1[-1] == "\\":
             _field1 = _field1[:-1]
             # if there are a \ character at the end it must be erased
-        _percentages = _field1.split(u"\\")
+        _percentages = _field1.split("\\")
         if len(_percentages) > 5:
             _percentages = _percentages[:5]
         # If there are no sufficient subfields, the subfields are added
         # with empty value:""
         else:
-            _percentages = _percentages + [u""]*(5-len(_percentages))
+            _percentages = _percentages + [""]*(5-len(_percentages))
         _percentage_titles = [ "CI", "GG", "BI", "BAJA", "IVA" ]
         _percentage_dict = {}
         for _percentage_index in range(len(_percentages)):
@@ -573,12 +583,12 @@
         _title_num = len(self.__budget.getTitleList()[1])
         if _title_num == 0: _title_num = 1
         # If the field 2 is empty, the field 0 is readed
-        if _field2 == u"":
+        if _field2 == "":
             # _____Field 0_____
-            if _field0[-1] == u"\\":
+            if _field0[-1] == "\\":
                 _field0 = _field0[:-1]
                 # if there are a \ character at the end it must be erased
-            _decimal_list = _field0.split(u"\\")
+            _decimal_list = _field0.split("\\")
             _decimal_index = 0
             if len(_decimal_list)%9 != 0:
                 # if it is not multiple of 9, empty subfield are added
@@ -779,7 +789,7 @@
         # If there are no sufficient fields, the fields are added
         # with empty value:""
         else:
-            field_list = field_list + [u""]*(7-len(field_list))
+            field_list = field_list + [""]*(7-len(field_list))
         # control character are erased: en of line, tab, space 
         # _____Fields_____
         _record_type = field_list[0]
@@ -790,13 +800,13 @@
         _dates = self.delete_control_space(field_list[5])
         _type = self.delete_control_space(field_list[6])
         # _____Code_____
-        _codes = _codes.split(u"\\")
+        _codes = _codes.split("\\")
         if len(_codes) > 0:
             # parse the hierarchy of the first code
             # hierarchy: 0->root, 1->Chapter/subchapter, 2->other
-            if len(_codes[0]) > 1 and _codes[0][-2:] == u"##":
+            if len(_codes[0]) > 1 and _codes[0][-2:] == "##":
                 _hierarchy = 0
-            elif len(_codes[0]) > 0 and _codes[0][-1:] == u"#":
+            elif len(_codes[0]) > 0 and _codes[0][-1:] == "#":
                 _hierarchy = 1
             else:
                 _hierarchy = 2
@@ -805,14 +815,15 @@
             # maximun len 20 characters
             _codes = [self.validateCode(_code) for _code in _codes]
         # empty codes are ignored
-        while u"" in _codes:
-            _codes.remove(u"")
+        while "" in _codes:
+            _codes.remove("")
         if len(_codes) > 0:
             #TODO: test this
             _code = _codes[0]
-            _synonyms = [synonym.encode("utf8") for synonym in _codes]
+            _synonyms = [synonym for synonym in _codes]
         else:
-            print(_("Record C without a valid code").encode("utf-8") )
+            _tuni = _("Record C without a valid code")
+            print(_tuni)
             return
         # _____Unit_____
         # nothing to do
@@ -820,13 +831,13 @@
         # nothing to do
         # _____Price_____ and _____Dates_____
         # last \ is erased
-        if len(_dates) > 0 and _dates[-1] == u"\\":
+        if len(_dates) > 0 and _dates[-1] == "\\":
             _dates = _dates[:-1]
-        if len(_prices) > 0 and _prices[-1] == u"\\":
+        if len(_prices) > 0 and _prices[-1] == "\\":
             _prices = _prices[:-1]
         interface.updateGui()
-        _dates = _dates.split(u"\\")
-        _prices = _prices.split(u"\\")
+        _dates = _dates.split("\\")
+        _prices = _prices.split("\\")
         # number of prices = number of titles in "V" line
         # if there are no sufficient prices it takes the last price defined
         _title_num = len(self.__budget.getTitleList()[1])
@@ -883,63 +894,63 @@
         #                    3 -> None,MC,MCr,MM,MS,ME,MCu,Mal,ML,M
         interface.updateGui()
         if _hierarchy == 0:
-            if _type == u"OB":
+            if _type == "OB":
                 _subtype = _type
                 _type = 0
-            elif _type == u"0" or _type == u"":
-                _subtype = u""
+            elif _type == "0" or _type == "":
+                _subtype = ""
                 _type = 0
             else:
-                print(utils.mapping(_("Incorrect type ($1) in the code $2"),
-                      (_type.encode("utf8"),
-                       _code.encode("utf8"))).encode("utf-8") )
+                _tuni = _("Incorrect type ($1) in the code $2")
+                _uni = utils.mapping(_tuni, (_type, _code))
+                print(_uni)
                 _type = 0
-                _subtype = u""
+                _subtype = ""
         elif _hierarchy == 1:
-            if _type == u"PU":
+            if _type == "PU":
                 _subtype = _type
                 _type = 0
-            elif _type == u"0" or _type == u"":
-                _subtype = u""
+            elif _type == "0" or _type == "":
+                _subtype = ""
                 _type = 0
             else:
-                print(utils.mapping(_("Incorrect type ($1) in the code $2"),
-                      (_type.encode("utf8"),
-                       _code.encode("utf8"))).encode("utf-8") )
+                _tuni = _("Incorrect type ($1) in the code $2")
+                _uni = utils.mapping(_tuni, (_type, _code))
+                print(_uni)
                 _type = 0
-                _subtype = u""
+                _subtype = ""
         else:
-            if _type == u"EA" or _type == u"EU" or _type == u"EC" or \
-               _type == u"EF" or _type == u"PA":
+            if _type == "EA" or _type == "EU" or _type == "EC" or \
+               _type == "EF" or _type == "PA":
                 _subtype = _type
                 _type = 0
-            elif _type == u"H":
+            elif _type == "H":
                 _subtype = _type
                 _type = 1
-            elif _type == u"Q" or _type == u"%":
+            elif _type == "Q" or _type == "%":
                 _subtype = _type
                 _type = 2
-            elif _type == u"MC" or _type == u"MCr" or _type == u"MM" or \
-                 _type == u"MS" or _type == u"ME" or _type == u"MCu" or \
-                 _type == u"Mal" or _type == u"ML" or _type == u"M":
+            elif _type == "MC" or _type == "MCr" or _type == "MM" or \
+                 _type == "MS" or _type == "ME" or _type == "MCu" or \
+                 _type == "Mal" or _type == "ML" or _type == "M":
                 _subtype = _type
                 _type = 3
-            elif _type == u"0" or _type == u"1" or _type == u"2" or \
-                 _type == u"3":
-                _subtype = u""
+            elif _type == "0" or _type == "1" or _type == "2" or \
+                 _type == "3":
+                _subtype = ""
                 _type = int(_type)
-            elif _type == u"":
-                _subtype = u""
+            elif _type == "":
+                _subtype = ""
                 _type = 0
             else:
-                print(utils.mapping(_("Incorrect type ($1) in the code $2"),
-                      (_type.encode("utf8"),
-                       _code.encode("utf8"))).encode("utf-8") )
+                _tuni = _("Incorrect type ($1) in the code $2")
+                _uni = utils.mapping(_tuni, (_type, _code))
+                print(_uni)
                 _type = 0
-                _subtype = u""
-        self.__budget.setRecord(_code.encode("utf8"), _synonyms, _hierarchy,
-            _unit.encode("utf8"), _summary.encode("utf8"),
-            _prices, _dates, _type, _subtype.encode("utf8"))
+                _subtype = ""
+        self.__budget.setRecord(_code, _synonyms, _hierarchy,
+            _unit, _summary,
+            _prices, _dates, _type, _subtype)
         self.__statistics.valid = self.__statistics.valid + 1
     
     def _parseDY(self, field_list, interface):
@@ -958,7 +969,7 @@
         # If there are no sufficient fields, the fields are added
         # with empty value:""
         else:
-            field_list = field_list + [u""]*(3-len(field_list))
+            field_list = field_list + [""]*(3-len(field_list))
         # control character are erased: end of line, tab, space 
         # _____Fields_____
         _record_type = field_list[0]
@@ -971,7 +982,7 @@
         _code = self.validateCode(_code)
         # _____children_____
         # TODO: test the number of decimals in factor an yield values
-        _children = _children.split(u"\\")
+        _children = _children.split("\\")
         _children_list = [ ]
         _child_index = 0
         interface.updateGui()
@@ -983,37 +994,37 @@
             # _____child_code_____
             _child_code = self.validateCode(_child_code)
             # _____factor_____
-            if _factor != u"":
+            if _factor != "":
                 try:
                     _factor = float(_factor)
                 except ValueError:
-                    print(utils.mapping(_("ValueError loadig the "\
+                    _tuni = _("ValueError loadig the "\
                           "descomposition of the record $1, the factor "\
                           "of the child $2 must be a float number and "\
-                          "can not be $3, seted default value 1.0"),
-                          (_code.encode("utf8"), _child_code.encode("utf8"),
-                           _factor.encode("utf8"))).encode("utf-8") )
+                          "can not be $3, seted default value 1.0")
+                    _uni = utils.mapping(_tuni, (_code, _child_code, _factor))
+                    print(_uni)
                     _factor = 1.0
             #____yield___
-            if _yield != u"":
+            if _yield != "":
                 try:
                     _yield = float(_yield)
                 except ValueError:
-                    print(utils.mapping(_("ValueError loading the "\
+                    _tuni = _("ValueError loading the "\
                           "descomposition of the record $1, the yield of "\
                           "the child $2, must be a float number and can"\
-                          "not be $3,  seted default value 1.0"),
-                           (_code.encode("utf8"), _child_code.encode("utf8"),
-                            _factor.encode("utf8"))).encode("utf-8") )
+                          "not be $3,  seted default value 1.0")
+                    _uni = utils.mapping(_tuni, (_code, _child_code, _factor))
+                    print(_uni)
                     _yield = 1.0
-            if _child_code != u"" and _code != u"":
+            if _child_code != "" and _code != "":
                 _children_list.append([_child_code, _factor, _yield ])
-            if _record_type == u"D":
-                _position = _child_index / 3
+            if _record_type == "D":
+                _position = _child_index // 3
             else: #_record_type == "Y"
                 _position = -1
-            self.__budget.setTree(_code.encode("utf8"),
-                _child_code.encode("utf8"), _position, _factor, 
+            self.__budget.setTree(_code,
+                _child_code, _position, _factor, 
                 _yield, "", "", "", "")
             _child_index = _child_index + 3
             interface.updateGui()
@@ -1044,7 +1055,7 @@
         # invalid characters are also erased
         _code = self.validateCode(_code) 
         # _____Text_____
-        self.__budget.setText(_code.encode("utf8"), _text.encode("utf8"))
+        self.__budget.setText(_code, _text)
         self.__statistics.valid = self.__statistics.valid + 1
 
     def _parseMN(self, field_list):
@@ -1052,10 +1063,10 @@
         
         field_list: field list of the record
             0- M or N: MEASURE or ADD MEASURE
-            1- [Parent Code\]Child Code
-            2- {Path\}
+            1- [Parent Code\\]Child Code
+            2- {Path\\}
             3- TOTAL MEASURE
-            4- {Type\Comment\Unit\Length\Width\Height\}
+            4- {Type\\Comment\\Unit\\Length\\Width\\Height\\}
             5- [Label]
         """
         # _____Number of fields_____
@@ -1066,7 +1077,7 @@
         # If there are no sufficient fields, the fields are added
         # with empty value:""
         else:
-            field_list = field_list + [u""]*(6-len(field_list))
+            field_list = field_list + [""]*(6-len(field_list))
         # control character are erased: end of line, tab, space
         # _____Fields_____
         _record_type = field_list[0]
@@ -1076,37 +1087,35 @@
         _lines = self.delete_control(field_list[4])
         _label = self.delete_control_space(field_list[5])
         # _____Codes_____
-        _code_list = _codes.split(u"\\")
+        _code_list = _codes.split("\\")
         # "#" and "##" characters at the end of the code are erased
         # invalid characters are also erased
         if len(_code_list) == 2:
             _parent_code = self.validateCode(_code_list[0]) 
-            if _parent_code == u"":
+            if _parent_code == "":
                 _parent_code = None
-            else:
-                _parent_code = _parent_code.encode("utf8")
-            _child_code =  self.validateCode(_code_list[1])
+            _child_code = self.validateCode(_code_list[1])
         elif len(_code_list) == 1:
-            _child_code =  self.validateCode(_code_list[0])
+            _child_code = self.validateCode(_code_list[0])
             _parent_code = None
         else:
-            print(utils.mapping(_("Invalid codes in $1 record, codes $2"),
-                  (_record_type.encode("utf8"),
-                   _codes.encode("utf8"))).encode("utf-8") )
+            _tuni = _("Invalid codes in $1 record, codes $2")
+            _uni = utils.mapping(_tuni, (_record_type, _codes))
+            print(_uni)
             return
-        if _child_code == u"":
-            print(utils.mapping(_("Empty child code in $1 record, codes: "\
-                  "$2"), (_record_type.encode("utf8"),
-                   _codes.encode("utf8"))).encode("utf-8") )
+        if _child_code == "":
+            _tuni = _("Empty child code in $1 record, codes: $2")
+            _uni = utils.mapping(_tuni, (_record_type, _codes))
+            print(_uni)
             return
         if _parent_code == None:
             # Empty parent code. No-estructured measures.
             pass
 
         # _____Path_____
-        _path_list = _path.split( u"\\" )
+        _path_list = _path.split( "\\" )
         if len(_path_list) > 0:
-            while len(_path_list) > 0 and _path_list[-1] == u"":
+            while len(_path_list) > 0 and _path_list[-1] == "":
                 _path_list = _path_list[:-1]
             if len(_path_list) == 0:
                 # Empty path. No-estructured measures. Path fixed to -2
@@ -1116,9 +1125,9 @@
             try:
                 _path = int(_path)
             except ValueError:
-                print(utils.mapping(_("Invalid path in $1 record, "\
-                      "codes $2"), (_record_type.encode("utf8"),
-                       _codes.encode("utf8"))).encode("utf-8") )
+                _tuni = _("Invalid path in $1 record, codes $2")
+                _uni = utils.mapping(_tuni, (_record_type, _codes))
+                print(_uni)
                 return
             if _path > 0:
                 _path -= 1
@@ -1128,21 +1137,21 @@
         try:
             _total = float(_total)
         except ValueError:
-            print(utils.mapping(_("Invalid Total Measure value in $1 "\
-                  "record, codes $2. Total fixed to 0."),
-                  (_record_type.encode("utf8"),
-                   _codes.encode("utf8"))).encode("utf-8") )
+            _tuni = _("Invalid Total Measure value in $1 "\
+                      "record, codes $2. Total fixed to 0.")
+            _uni = utils.mapping(_tuni, (_record_type, _codes))
+            print(_uni)
             _total = 0
         # _____Measure lines_____
-        _lines = _lines.split(u"\\")
+        _lines = _lines.split("\\")
         _line_index = 0
         _line_list = [ ]
         while _line_index < len(_lines)-6:
             _linetype = _lines[_line_index]
-            if _linetype == u"":
+            if _linetype == "":
                 _linetype = 0
-            elif _linetype == u"1" or _linetype == u"2" or \
-                   _linetype == u"3":
+            elif _linetype == "1" or _linetype == "2" or \
+                   _linetype == "3":
                     _linetype = int(_linetype)
             else:
                 _linetype = 0
@@ -1150,47 +1159,48 @@
             if _linetype == 3:
                 # "formula": ".*[^0123456789\.()\+\-\*/\^abcdp ].*"
                 if self.__pattern["formula"].match(_comment):
-                    print(utils.mapping(_("The comment is not a formula or "\
-                          "its have invalid characters, in the $1 record, "\
-                          "codes $2"), (_record_type.encode("utf8"),
-                           _codes.encode("utf8"))).encode("utf-8") )
+                    _tuni = _("The comment is not a formula or "\
+                              "its have invalid characters, in the $1 record, "\
+                              "codes $2")
+                    _uni = utils.mapping(_tuni, (_record_type, _codes))
+                    print(_uni)
                     return
                 else:
-                    _formula = _comment.encode("utf8")
+                    _formula = _comment
                     _comment = ""
             else:
                 _formula = ""
-                _comment = _comment.encode("utf8")
             _units = _lines[_line_index + 2]
-            _units = self.__pattern["no_float"].sub(u"", _units)
+            _units = self.__pattern["no_float"].sub("", _units)
             _length = _lines[_line_index + 3]
-            _length = self.__pattern["no_float"].sub(u"", _length)
+            _length = self.__pattern["no_float"].sub("", _length)
             _width = _lines[_line_index + 4]
-            _width  = self.__pattern["no_float"].sub(u"", _width)
+            _width  = self.__pattern["no_float"].sub("", _width)
             _height = _lines[_line_index + 5]
-            _height  = self.__pattern["no_float"].sub(u"", _height)
+            _height  = self.__pattern["no_float"].sub("", _height)
 
             try:
-                if _units != u"":
+                if _units != "":
                     _units = float(_units)
-                if _length != u"": _length = float(_length)
-                if _width != u"": _width = float(_width)
-                if _height != u"": _height = float(_height)
+                if _length != "": _length = float(_length)
+                if _width != "": _width = float(_width)
+                if _height != "": _height = float(_height)
             except ValueError:
-                print(utils.mapping(_("The measure values are not float "\
-                      "numbers, code $1"),
-                      (_codes.encode("utf8"),)).encode("utf-8") )
+                _tuni = _("The measure values are not float "\
+                          "numbers, code $1")
+                _uni = utils.mapping(_tuni, (_codes,))
+                print(_uni)
                 return
             # Prevent subfield units remains empty.
-            if (_units == u"" and (_length != u"" or _width != u""
-                                   or _height != u"")):
+            if (_units == "" and (_length != "" or _width != ""
+                                   or _height != "")):
                 _units = 1.0
             _line_list.append([_linetype, _comment, _units,
                                _length, _width, _height, _formula])
             _line_index = _line_index + 6
-        self.__budget.setTree(_parent_code, _child_code.encode("utf8"), _path, "", "",
-                           _total, _line_list, _label.encode("utf8"),
-                           _record_type.encode("utf8"))
+        self.__budget.setTree(_parent_code, _child_code, _path, "", "",
+                           _total, _line_list, _label,
+                           _record_type)
         self.__statistics.valid = self.__statistics.valid + 1
 
     def _parseW(self, field_list):
@@ -1212,9 +1222,9 @@
         # _____Fields_____
         _code_fields = field_list[0]
         # last \ is erased
-        if len(_code_fields) and _code_fields[-1] == u"\\":
+        if len(_code_fields) and _code_fields[-1] == "\\":
             _code_fields = _code_fields[:-1]
-        _code_fields = _code_fields.split(u"\\")
+        _code_fields = _code_fields.split("\\")
         _field_dict = {}
         _field_index = 0
         while _field_index < len(_code_fields)-1:
@@ -1226,10 +1236,8 @@
             #"control": "[\t \n\r]"
             _field_code = self.delete_control_space(_field_code)
             # _____section_title_____
-            if _field_code != u"":
-                _e_field_code = _field_code.encode("utf8")
-                _e_field_title = _field_title.encode("utf8")
-                _field_dict[_e_field_code] = _e_field_title
+            if _field_code != "":
+                _field_dict[_field_code] = _field_title
             _field_index = _field_index + 2
         self.__budget.setSheetFields(_field_dict)
         self.__statistics.valid = self.__statistics.valid +1
@@ -1253,7 +1261,7 @@
         if len(field_list) < 3:
             return
         _code = field_list[1]
-        if _code == u"":
+        if _code == "":
             # A: Section Titles
             # Any INFORMATION after last field separator is ignored
             # The record must have 3 fields
@@ -1263,9 +1271,9 @@
             # _____Fields_____
             _section_codes = field_list[1]
             # last \ is erased
-            if len(_section_codes) and _section_codes[-1] == u"\\":
+            if len(_section_codes) and _section_codes[-1] == "\\":
                 _section_codes = _section_codes[:-1]
-            _section_codes = _section_codes.split(u"\\")
+            _section_codes = _section_codes.split("\\")
             _section_dict = {}
             _section_index = 0
             while _section_index < len(_section_codes)-1:
@@ -1278,10 +1286,8 @@
                 _section_code = self.delete_control_space(_section_code)
                 # _____section_title_____
                 _section_title = self.delete_control_space(_section_title)
-                if _section_code != u"":
-                    _e_section_code = _section_code.encode("utf8")
-                    _e_section_title = _section_title.encode("utf8")
-                    _section_dict[_e_section_code] = _e_section_title
+                if _section_code != "":
+                    _section_dict[_section_code] = _section_title
                 _section_index = _section_index + 2
             self.__budget.setSheetSections(_section_dict)
             self.__statistics.valid = self.__statistics.valid +1
@@ -1299,16 +1305,16 @@
             # invalid characters are also erased
             _record_code = self.validateCode(_record_code)
             _scodes_text = field_list[1]
-            if _scodes_text == u"":
+            if _scodes_text == "":
                 # TODO: rtf and html files
-                _str = "Html and rtf files not yet implemented in ~L record"
-                print(_str.encode("utf-8") )
+                _uni = "Html and rtf files not yet implemented in ~L record"
+                print(_uni)
             else:
                 # _____Section-code_Section-text_____
                 # last \ is erased
-                if len(_scodes_text) and _scodes_text[-1] == u"\\":
+                if len(_scodes_text) and _scodes_text[-1] == "\\":
                     _scodes_text = _scodes_text[:-1]
-                _scodes_text = _scodes_text.split(u"\\")
+                _scodes_text = _scodes_text.split("\\")
                 _paragraph_dict = {}
                 _section_dict = {}
                 _section_index = 0
@@ -1320,18 +1326,14 @@
                     # _____section_code_____
                     _section_code = self.delete_control_space(_section_code)
                     # _____section_text_____
-                    if _section_code != u"" and _section_text != u"":
+                    if _section_code != "" and _section_text != "":
                         #-# paragraph #-#
-                        _paragraph_code = _record_code + _section_code + u"*"
-                        _e_paragraph_code = _paragraph_code.encode("utf8")
-                        _e_section_text = _section_text.encode("utf8")
-                        _paragraph_dict[_e_paragraph_code] = _e_section_text
-                        _e_section_code = _section_code.encode("utf8")
-                        _section_dict[_e_section_code] = _e_paragraph_code
+                        _paragraph_code = _record_code + _section_code + "*"
+                        _paragraph_dict[_paragraph_code] = _section_text
+                        _section_dict[_section_code] = _paragraph_code
                     _section_index = _section_index + 2
                 self.__budget.setSheetParagraphs(_paragraph_dict)
-                self.__budget.setSheetRecord(_record_code.encode("utf8"), "*",
-                                             _section_dict)
+                self.__budget.setSheetRecord(_record_code, "*", _section_dict)
                 self.__statistics.valid = self.__statistics.valid +1
     
     def _parseQ(self, field_list):
@@ -1360,9 +1362,9 @@
         _record_code = self.validateCode(_record_code)
         _scodes_pkey = field_list[1]
         # last \ is erased
-        if len(_scodes_pkey) and _scodes_pkey[-1] == u"\\":
+        if len(_scodes_pkey) and _scodes_pkey[-1] == "\\":
             _scodes_pkey = _scodes_pkey[:-1]
-        _scodes_pkey = _scodes_pkey.split(u"\\")
+        _scodes_pkey = _scodes_pkey.split("\\")
         _field_dict = {}
         _section_index = 0
         while _section_index < len(_scodes_pkey) -1:
@@ -1378,24 +1380,21 @@
             # _____Fields keys_____
             _field_keys = self.delete_control_space(_field_keys)
             # last ; is erased
-            if len(_field_keys) and _field_keys[-1] == u";":
+            if len(_field_keys) and _field_keys[-1] == ";":
                 _field_keys = _field_keys[:-1]
-            _field_keys_list = _scodes_pkey.split(u";")
+            _field_keys_list = _scodes_pkey.split(";")
             for _field_key in _field_keys_list:
-                if _field_key != u"" and _section_code != u"" and \
-                   _paragraph_key != u"":
+                if _field_key != "" and _section_code != "" and \
+                   _paragraph_key != "":
                     if _field_key in _field_dict:
                         _section_dict = _field_dict[_field_key]
                     else:
                         _section_dict = {}
                         _field_dict[_field_key] = _section_dict
-                    _e_section_code = _section_code.encode("utf8")
-                    _e_paragraph_code = _paragraph_code.encode("utf8")
-                    _section_dict[_e_section_code] = _e_paragraph_code
+                    _section_dict[_section_code] = _paragraph_code
             _section_index = _section_index + 3
-        for _field, _section_dict in _field_dict.iteritems():
-            self.__budget.setSheetRecord(_record_code.encode("utf8"),
-                                         _field.encode("utf8"), _section_dict)
+        for _field, _section_dict in _field_dict.items():
+            self.__budget.setSheetRecord(_record_code, _field, _section_dict)
         self.__statistics.valid = self.__statistics.valid +1
     
     def _parseJ(self, field_list):
@@ -1422,13 +1421,12 @@
         _paragraph_code = self.delete_control_space(field_list[0])
         # _____Paragraph text_____
         _paragraph_text = field_list[1]
-        if _paragraph_text == u"":
+        if _paragraph_text == "":
             # TODO: rtf and html files
-            _str = "Html and rtf files not yet implemented in ~J record"
-            print(_str.encode("utf-8") )
+            _uni = "Html and rtf files not yet implemented in ~J record"
+            print(_uni)
         else:
-            self.__budget.setSheetParagraph(paragraph_code.encode("utf8"),
-                                            paragraph_text.encode("utf8"))
+            self.__budget.setSheetParagraph(paragraph_code, paragraph_text)
             self.__statistics.valid = self.__statistics.valid +1
     
     def _parseG(self, field_list):
@@ -1458,18 +1456,17 @@
         _grafic_files = self.delete_control(field_list[1])
         # _____subfields_____
         # last \ is erased
-        if len(_grafic_files) and _grafic_files[-1] == u"\\":
+        if len(_grafic_files) and _grafic_files[-1] == "\\":
             _grafic_files = _grafic_files[:-1]
-        _grafic_file_list = _grafic_files.split(u"\\")
+        _grafic_file_list = _grafic_files.split("\\")
         _tested_grafic_file_list = []
         for _grafic_file in _grafic_file_list:
-            _str_grafic_file = _grafic_file.encode("utf8")
-            _path = os.path.dirname(self.__filename).encode("utf8")
-            _grafic_file_path = os.path.join(_path, _str_grafic_file)
+            _path = os.path.dirname(self.__filename)
+            _grafic_file_path = os.path.join(_path, _grafic_file)
             if os.path.exists(_grafic_file_path):
                 _tested_grafic_file_list.append(_grafic_file_path)
             else:
-                _name_ext = os.path.splitext(_str_grafic_file)
+                _name_ext = os.path.splitext(_grafic_file)
                 _grafic_file_name = _name_ext[0]
                 _grafic_file_ext = _name_ext[1]
                 _grafic_file_name_u = _grafic_file_name.upper()
@@ -1493,12 +1490,12 @@
                 elif os.path.exists(_grafic_file_path_ll):
                     _tested_grafic_file_list.append(_grafic_file_path_ll)
                 else:
-                    print(utils.mapping(_("The file $1 do not exist"),
-                        (_grafic_file_path.decode("utf8"),)).encode("utf-8") )
+                    _tuni = _("The file $1 do not exist")
+                    _uni = utils.mapping(_tuni, (_grafic_file_path,))
+                    print(_uni)
         if len(_grafic_file_list) > 0:
             for _grafic_file in _tested_grafic_file_list:
-                self.__budget.addFile(_record_code.encode("utf8"),
-                                      _grafic_file, "img", "")
+                self.__budget.addFile(_record_code, _grafic_file, "img", "")
             self.__statistics.valid = self.__statistics.valid +1
     
     def _parseE(self, field_list):
@@ -1523,11 +1520,11 @@
         # If there are no sufficient fields, the fields are added
         # with empty value:""
         else:
-            field_list = field_list[1:] + [u""]*(6-len(field_list))
+            field_list = field_list[1:] + [""]*(6-len(field_list))
         # _____Fields_____
         # _____company Code_____
         _company_code = self.delete_control_space(field_list[0])
-        if _company_code == u"":
+        if _company_code == "":
             return
         # _____Summary_____
 
@@ -1538,15 +1535,15 @@
         _local_offices = self.delete_control(field_list[3])
         # _____subfields of local_offices_____
         # last \ is erased
-        if len(_local_offices) and _local_offices[-1] == u"\\":
+        if len(_local_offices) and _local_offices[-1] == "\\":
             _local_offices = _local_offices[:-1]
-        _local_offices_list = _local_offices.split(u"\\")
+        _local_offices_list = _local_offices.split("\\")
         # If there are no sufficent subfields, the subfields are added 
         # whith empty value
         _nsub = len(_local_offices_list) % 10
         if _nsub != 0:
             _local_offices_list = _local_offices_list + \
-                                   [u""]*(10-len(field_list))
+                                   [""]*(10-len(field_list))
         _local_offices = []
         _local_offices_index = 0
         while _local_offices_index < len(_local_offices_list)-9:
@@ -1560,49 +1557,47 @@
             _country = _local_offices_list[_local_offices_index+6]
             _phone = _local_offices_list[_local_offices_index+7]
             # last ; is erased
-            if len(_phone) and _phone[-1] == u";":
+            if len(_phone) and _phone[-1] == ";":
                 _phone = _phone[:-1]
-            _phone_list = _phone.split(u";")
-            _phone_list = [_phone.encode("utf8") for _phone in _phone_list]
+            _phone_list = _phone.split(";")
             _fax = _local_offices_list[_local_offices_index+8]
             # last ; is erased
-            if len(_fax) and _fax[-1] == u";":
+            if len(_fax) and _fax[-1] == ";":
                 _fax = _fax[:-1]
-            _fax_list = _fax.split(u";")
-            _fax_list = [_fax.encode("utf8") for _fax in _fax_list]
+            _fax_list = _fax.split(";")
             _contact_person = _local_offices_list[_local_offices_index+9]
-            if _type != u"" or _subname != u"" or _address != u"" or \
-               _postal_code != u"" or _town != u"" or _province != u"" or \
-               _country != u"" or _phone != u"" or _fax != u"" or \
-               _contact_person != u"":
-                _local_offices.append([_type.encode("utf8"),
-                                       _subname.encode("utf8"),
-                                       _address.encode("utf8"),
-                                       _postal_code.encode("utf8"),
-                                       _town.encode("utf8"),
-                                       _province.encode("utf8"),
-                                       _country.encode("utf8"),
+            if _type != "" or _subname != "" or _address != "" or \
+               _postal_code != "" or _town != "" or _province != "" or \
+               _country != "" or _phone != "" or _fax != "" or \
+               _contact_person != "":
+                _local_offices.append([_type,
+                                       _subname,
+                                       _address,
+                                       _postal_code,
+                                       _town,
+                                       _province,
+                                       _country,
                                        _phone_list,
                                        _fax_list,
-                                       _contact_person.encode("utf8")])
+                                       _contact_person])
             _local_offices_index = _local_offices_index + 10
         # _____cif web email_____
         _c_w_e = self.delete_control_space(field_list[4])
         # last \ is erased
-        if len(_c_w_e) and _c_w_e[-1] == u"\\":
+        if len(_c_w_e) and _c_w_e[-1] == "\\":
             _c_w_e = _c_w_e[:-1]
-        _c_w_e_list = _c_w_e.split(u"\\")
+        _c_w_e_list = _c_w_e.split("\\")
         # _____subfields_____
         # If there are no sufficient fields, the fields are added
         # with empty value:""
-        _c_w_e_list = _c_w_e_list + [u""]*(3-len(_c_w_e_list))
+        _c_w_e_list = _c_w_e_list + [""]*(3-len(_c_w_e_list))
         _cif = _c_w_e_list[0]
         _web = _c_w_e_list[1]
         _email = _c_w_e_list[2]
-        self.__budget.setCompany(_company_code.encode("utf8"),
-                    _sumamary.encode("utf8"), _name.encode("utf8"), 
-                    _local_offices, _cif.encode("utf8"),
-                    _web.encode("utf8"), _email.encode("utf8"))
+        self.__budget.setCompany(_company_code,
+                    _sumamary, _name, 
+                    _local_offices, _cif,
+                    _web, _email)
         self.__statistics.valid = self.__statistics.valid +1
     
     def _parseX(self, field_list):
@@ -1631,35 +1626,34 @@
         # "control": "[\t \n\r]"
         _field_1 = self.delete_control_space(field_list[0])
         _field_2 = self.delete_control_space(field_list[1])
-        if _field_1 == u"":
+        if _field_1 == "":
             # A)
-            _field_2_list = _field_2.split(u"\\")
+            _field_2_list = _field_2.split("\\")
             _ti_index = 0
             while _ti_index < len(_field_2_list)-3:
                 _ti_code = _field_2_list[_ti_index]
                 _ti_description = _field_2_list[_ti_index+1]
                 _ti_unit = _field_2_list[_ti_index+2]
                 if _ti_code != "":
-                    self.__budget.addTecInfo(_ti_code.encode("utf8"), 
-                                             _ti_description.encode("utf8"),
-                                             _ti_unit.encode("utf8"))
+                    self.__budget.addTecInfo(_ti_code, 
+                                             _ti_description,
+                                             _ti_unit)
                 _ti_index = _ti_index + 3
         else:
             # B)
             # "#" and "##" characters at the end of the code are erased
             # invalid characters are also erased
             _record_code = self.validateCode(_field_1)
-            _field_2_list = _field_2.split(u"\\")
+            _field_2_list = _field_2.split("\\")
             _ti_index = 0
             _ti_dict = {}
             while _ti_index < len(_field_2_list)-2:
                 _ti_code = _field_2_list[_ti_index]
                 _ti_value = _field_2_list[_ti_index+1]
-                if _ti_code != u"" and _ti_value != u"":
-                    _ti_dict[_ti_code.encode("utf8")] = _ti_value.encode("utf8")
+                if _ti_code != "" and _ti_value != "":
+                    _ti_dict[_ti_code] = _ti_value
                 _ti_index = _ti_index + 2
-            self.__budget.setTecnicalInformation(_record_code.encode("utf8"),
-                                                 _ti_dict)
+            self.__budget.setTecnicalInformation(_record_code, _ti_dict)
         self.__statistics.valid = self.__statistics.valid +1
 
     def _parseF(self, field_list):
@@ -1689,16 +1683,16 @@
         _files = self.delete_control(field_list[1])
         # _____subfields_____
         # last \ is erased
-        if len(_files) and _files[-1] == u"\\":
+        if len(_files) and _files[-1] == "\\":
             _files = _files[:-1]
-        _files_list = _files.split(u"\\")
+        _files_list = _files.split("\\")
         # adding empty subfiels if necesary
         if len(_files_list)%3 > 0:
-            _files_list.extend[u""]*(3 - len(_files_list)%3)
+            _files_list.extend[""]*(3 - len(_files_list)%3)
         _file_index = 0
         _tested_files_list = []
         while _file_index < len(_files_list)-3:
-            _type = _files_list[_file_index].replace(u" ",u"")
+            _type = _files_list[_file_index].replace(" ","")
             ## _types = {
             ##           "0": _("others"),
             ##           "1": _("características técnicas y de fabricación"),
@@ -1714,23 +1708,23 @@
             ##                  "etc. de empresa"),
             ##          "11": _("certificado/s de empresa"),
             ##          "12": _("obras realizadas")}
-            _types = [u"0", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8",
-                      u"9", u"10", u"11", u"12"]
+            _types = ["0", "1", "2", "3", "4", "5", "6", "7", "8",
+                      "9", "10", "11", "12"]
             if not _type in _types:
-                _type = u"0"
+                _type = "0"
             _filenames = _files_list[_file_index + 1]
             _description = _files_list[_file_index + 2]
             _file_index += 3
-            if len(_filenames) and _filenames[-1] == u";":
+            if len(_filenames) and _filenames[-1] == ";":
                 _files = _files[:-1]
-            _filenames_list = _filenames.split(u";")
+            _filenames_list = _filenames.split(";")
             
             _path = os.path.dirname(self.__filename)
             for _filename in _filenames_list:
-                _file_path = os.path.join(_path, _filename.encode("utf8"))
+                _file_path = os.path.join(_path, _filename)
                 if os.path.exists(_file_path):
-                    _tested_files_list.append([_file_path, _type.encode("utf8"),
-                                               _description.encode("utf8")])
+                    _tested_files_list.append([_file_path, _type,
+                                               _description])
                 else:
                     _name_ext = os.path.splitext(_filename)
                     _file_name = _name_ext[0]
@@ -1749,26 +1743,27 @@
                     _file_path_ll = os.path.join(_path, _ll)
                     if os.path.exists(_file_path_uu):
                         _tested_files_list.append([_file_path_uu,
-                                                   _type.encode("utf8"),
-                                                   _description.encode("utf8")])
+                                                   _type,
+                                                   _description])
                     elif os.path.exists(_grafic_file_path_ul):
                         _tested_files_list.append([_file_path_ul,
-                                                   _type.encode("utf8"),
-                                                   _description.encode("utf8")])
+                                                   _type,
+                                                   _description])
                     elif os.path.exists(_grafic_file_path_lu):
                         _tested_files_list.append([_file_path_lu,
-                                                   _type.encode("utf8"),
-                                                   _description.encode("utf8")])
+                                                   _type,
+                                                   _description])
                     elif os.path.exists(_grafic_file_path_ll):
                         _tested_files_list.append([_file_path_ll,
-                                                   _type.encode("utf8"),
-                                                   _description.encode("utf8")])
+                                                   _type,
+                                                   _description])
                     else:
-                        print(utils.mapping(_("The file $1 do not exist"),
-                            (_file_path,)).encode("utf-8") )
+                        _tuni = _("The file $1 do not exist")
+                        _uni = utils.mapping(_tuni, (_file_path,))
+                        print(_uni)
         if len(_tested_files_list) > 0:
             for _file in _tested_files_list:
-                self.__budget.addFile(_record_code.encode("utf8"), _file[0],
+                self.__budget.addFile(_record_code, _file[0],
                                       _file[1], _file[2])
         self.__statistics.valid = self.__statistics.valid +1
 
@@ -1829,13 +1824,13 @@
         # _____Labels_____
         # last \ is erased
         # TODO: change the others parsers to this:
-        while len(_labels) > 0 and _labels[-1] == u"\\":
+        while len(_labels) > 0 and _labels[-1] == "\\":
             _labels = _labels[:-1]
         # replace "_" to " "
-        _labels = _labels.replace(u"_",u" ")
-        _label_list = _labels.split(u"\\")
+        _labels = _labels.replace("_"," ")
+        _label_list = _labels.split("\\")
         for _label in _label_list:
-            self.__budget.addLabel(_code.encode("utf8"), _label.encode("utf8"))
+            self.__budget.addLabel(_code, _label)
         self.__statistics.valid = self.__statistics.valid + 1
 
     def _parseP(self, field_list):
@@ -1856,13 +1851,13 @@
         if len(field_list) > 2:
             # delete control caracters and spaces
             _family_code = self.delete_control_space(field_list[1])
-            if _family_code == u"": # A)Global paremetric record
+            if _family_code == "": # A)Global paremetric record
                 # The record must have 3 or 4 fields
                 if len(field_list) > 4:
                     field_list = field_list[0:4]
                 field_list = field_list[1:]
                 if len(field_list) == 2:
-                    field_list.append(u"")
+                    field_list.append("")
                 if len(field_list) != 3:
                     return
             else: # B)Family Parametric record
@@ -1871,22 +1866,24 @@
                     field_list = field_list[0:3]
                 field_list = field_list[1:]
                 if len(field_list) != 2:
-                    print(_("PyArq hates parametric DLLs").encode("utf-8") )
+                    _tuni = _("PyArq hates parametric DLLs")
+                    print(_uni)
                     return
         else:
             return
         # _____Description_____
         _description = field_list[1]
-        if _description == u"":
-            print(_("PyArq hates parametric DLLs").encode("utf-8") )
+        if _description == "":
+            _tuni = _("PyArq hates parametric DLLs")
+            print(_tuni)
             return
         # Adding last end of line
-        _description = _description + u"\r\n"
+        _description = _description + "\r\n"
         # Delete comments
         # "comment" : "#.*\r\n"
-        _description = self.__pattern["comment"].sub(u"\r\n",_description)
+        _description = self.__pattern["comment"].sub("\r\n",_description)
         # Tabs to spaces
-        _description = _description.replace(u"\t",u" ")
+        _description = _description.replace("\t"," ")
         # Delete empty lines
         # "empty_line": r"(\r\n) *\r\n"
         while self.__pattern["empty_line"].search(_description):
@@ -1895,12 +1892,12 @@
         # Delete spaces before and after /
         # "space_before_backslash" : r"( )+\\"
         _description = self.__pattern["space_before_backslash"].sub(
-                        ur"\\",_description)
+                        r"\\",_description)
         # "space_after_backslash" : r"\\( )+"
         _description = self.__pattern["space_after_backslash"].sub(
-                        ur"\\",_description)
+                        r"\\",_description)
         # Join lines that start but not end with /
-        _description = u"\r\n" + _description # add leading end of line
+        _description = "\r\n" + _description # add leading end of line
         # "start_noend_backslash": "(\r\n\\\.*[^\\\])\r\n"
         while self.__pattern["start_noend_backslash"].search(_description):
             _description = self.__pattern["start_noend_backslash"].sub(
@@ -1916,8 +1913,8 @@
                             lambda x: x.groups()[0], _description)
         _description = _description[2:]  # remove leading end of line
         #_description = re.sub(r"\\( )+",r"\\",_description)
-        _lines = _description.split(u"\r\n")
-        _final_description = u""
+        _lines = _description.split("\r\n")
+        _final_description = ""
         _pass_line = 0
         for index in range(len(_lines)):
             _line = _lines[index]
@@ -1925,39 +1922,39 @@
             if len(_line) != 0: # Delete empty lines
                 if _pass_line > 0:
                     _pass_line = _pass_line -1
-                    _line = u""
+                    _line = ""
                 elif _line.isspace():
-                    _line = u""
-                elif  _line[0] != u"\\":
+                    _line = ""
+                elif  _line[0] != "\\":
                     # Delete spaces out "" delimiter
                     _list = _line.split(u'"')
-                    _final_line = u""
+                    _final_line = ""
                     for index1 in range(len(_list)):
                         if index1 % 2 != 0:
                             _parcial_line = u'"' + _list[index1]
                         else:
-                            _parcial_line = _list[index1].replace(u" ",u"")
+                            _parcial_line = _list[index1].replace(" ","")
                             _parcial_line = u'"' + _parcial_line
                         _final_line = _final_line + _parcial_line
                     _line = _final_line[1:]
                     _lines[index] = _line
                     # parse data
-                    if len(_line) > 2 and _line[:2] == u"::":
+                    if len(_line) > 2 and _line[:2] == "::":
                         # Delete spaces out " delimiter
                         #print("__PRECIO__" + _line[2:])
                         pass
-                    elif len(_line) > 2 and _line[:2] == u"%:":
+                    elif len(_line) > 2 and _line[:2] == "%:":
                         # Delete spaces out " delimiter
                         #print("__%AUX__" + _line[2:])
                         pass
-                    elif len(_line) > 3 and _line[:2] == u"%%:":
+                    elif len(_line) > 3 and _line[:2] == "%%:":
                         # Delete spaces out " delimiter
                         #print("__%%AUX__" + _line[2:] )
                         pass
                     elif self.__pattern["var"].search(_line):
                         # Delete spaces out " delimiter
                         #print( "line =", _line )
-                        while _line.count(u'"') % 2 == 1 and \
+                        while _line.count('"') % 2 == 1 and \
                               index + _pass_line + 1 < len(_lines) -1:
                             _line = _line + _lines[index + _pass_line + 1]
                             _pass_line = _pass_line + 1
@@ -1965,7 +1962,7 @@
                         if _search is not None:
                             _var0 = _search.groups()[0]
                             _var1 = _search.groups()[1]
-                            _var = _var0 + u" = " + _var1
+                            _var = _var0 + " = " + _var1
                             #print("__VAR__" + str(_var) )
                             pass
                         else:
@@ -1978,84 +1975,85 @@
                         if _search is not None:
                             _var0 = _search.groups()[0]
                             _var1 = _search.groups()[1]
-                            _var = _var0  + u":" + _var1
+                            _var = _var0  + ":" + _var1
                             #print( "__Descomposición__" + str(_var) )
                             pass
                         else:
                             #print("no __Descomposición__", _line )
                             pass
                     else:
-                        _str = "Parametric: code: " + \
-                               _family_code.encode("utf8")
-                        print(_str.encode("utf-8") )
-                        _str = "******* Desconocido *** : " + _line
-                        print(_str.encode("utf-8") )
+                        _tuni = _("Parametric: code:  $1")
+                        _uni = utils.mapping(_tuni, (_family_code,))
+                        print(_uni)
+                        _tuni = _("******* Desconocido *** : $1")
+                        _uni = utils.mapping(_tuni, (_line,))
+                        print(_uni)
                         if index-10 > 0:
-                            print("-11 : " + _lines[index-11].encode("utf8") )
+                            print("-11 : " + _lines[index-11] )
                         if index-10 > 0:
-                            print("-10 : " + _lines[index-10].encode("utf8") )
+                            print("-10 : " + _lines[index-10] )
                         if index-9 > 0:
-                            print("-9 : " + _lines[index-9].encode("utf8") )
+                            print("-9 : " + _lines[index-9] )
                         if index-8 > 0:
-                            print("-8 : " + _lines[index-8].encode("utf8") )
+                            print("-8 : " + _lines[index-8] )
                         if index-7 > 0:
-                            print("-7 : " + _lines[index-7].encode("utf8") )
+                            print("-7 : " + _lines[index-7] )
                         if index-6 > 0:
-                            print("-6 : " + _lines[index-6].encode("utf8") )
+                            print("-6 : " + _lines[index-6] )
                         if index-5 > 0:
-                            print("-5 : " + _lines[index-5].encode("utf8") )
+                            print("-5 : " + _lines[index-5] )
                         if index-4 > 0:
-                            print("-4 : " + _lines[index-4].encode("utf8") )
+                            print("-4 : " + _lines[index-4] )
                         if index-3 > 0:
-                            print("-3 : " + _lines[index-3].encode("utf8") )
+                            print("-3 : " + _lines[index-3] )
                         if index-2 > 0:
-                            print("-2 : " + _lines[index-2].encode("utf8") )
+                            print("-2 : " + _lines[index-2] )
                         if index-1 > 0:
-                            print("-1 : " + _lines[index-1].encode("utf8") )
-                        print(("-0 :" + _lines[index-0]).encode("utf-8") )
+                            print("-1 : " + _lines[index-1] )
+                        print(("-0 :" + _lines[index-0]) )
                         pass
                 else:
-                    _parameter_list = _line.split(u"\\")[1:-1]
+                    _parameter_list = _line.split("\\")[1:-1]
                     if len(_parameter_list) >= 2:
-                        if _parameter_list[0] == u"C" or \
-                           _parameter_list[0] == u"COMENTARIO":
+                        if _parameter_list[0] == "C" or \
+                           _parameter_list[0] == "COMENTARIO":
                             #print( "__COMENTARIO__" + _parameter_list[1])
                             self.__budget.setParametricSelectComment(
-                                _family_code.encode("utf8"),
-                                _parameter_list[1].encode("utf8"))
-                        elif _parameter_list[0] == u"R" or \
-                           _parameter_list[0] == u"RESUMEN":
+                                _family_code,
+                                _parameter_list[1])
+                        elif _parameter_list[0] == "R" or \
+                           _parameter_list[0] == "RESUMEN":
                             #print( "__RESUMEN__" + _parameter_list[1])
                             self.__budget.setParametricSummary(
-                                _family_code.encode("utf8"),
-                                _parameter_list[1].encode("utf8"))
-                        elif _parameter_list[0] == u"T" or \
-                           _parameter_list[0] == u"TEXTO":
+                                _family_code,
+                                _parameter_list[1])
+                        elif _parameter_list[0] == "T" or \
+                           _parameter_list[0] == "TEXTO":
                             #print( "__TEXTO__" + _parameter_list[1])
                             self.__budget.setParametricText(
-                                _family_code.encode("utf8"),
-                                _parameter_list[1].encode("utf8"))
-                        elif _parameter_list[0] == u"P" or \
-                           _parameter_list[0] == u"PLIEGO":
+                                _family_code,
+                                _parameter_list[1])
+                        elif _parameter_list[0] == "P" or \
+                           _parameter_list[0] == "PLIEGO":
                             #print( "__PLIEGO__" + str(_parameter_list[1:]) )
                             pass
-                        elif _parameter_list[0] == u"K" or \
-                           _parameter_list[0] == u"CLAVES":
+                        elif _parameter_list[0] == "K" or \
+                           _parameter_list[0] == "CLAVES":
                             #print( "__CLAVES__" + str(_parameter_list[1:]) )
                             pass
-                        elif _parameter_list[0] == u"F" or \
-                           _parameter_list[0] == u"COMERCIAL":
+                        elif _parameter_list[0] == "F" or \
+                           _parameter_list[0] == "COMERCIAL":
                             #print( "__COMERCIAL__" + str(_parameter_list[1:]) )
                             pass
                         else:
                             #print( "==PARAMETRO==" + str(_parameter_list[:]) )
                             pass
-                _final_description = _final_description + _line + u"\r\n"
+                _final_description = _final_description + _line + "\r\n"
                 
                 #print( _line )
         # Delete last empty line
         _description = _final_description[:-2]
-        _lines = _description.split(u"\r\n")
+        _lines = _description.split("\r\n")
         for _line in _lines:
             pass
             #print( _line )
@@ -2088,25 +2086,29 @@
         interface.readFile_set_statistics(self.__statistics)
         _time = time.time()
         try:
-            _file =  open(self.__filename, 'r')
+            _file =  open(self.__filename, 'rb')
         except IOError:
-            _str = utils.mapping("IOError: $1", (self.__filename,))
-            print( _str.encode("utf-8") )
+            _tuni = "IOError: $1"
+            _uni = utils.mapping(_tuni, (self.__filename,))
+            print(_uni)
             return None
         _filesize = float(os.path.getsize(self.__filename))
         if _filesize == 0.0:
-            _str = utils.mapping("Empty File: $1", (self.__filename,))
-            print( _str.encode("utf-8") )
+            _tuni = "Empty File: $1"
+            _uni = utils.mapping(_uni, (self.__filename,))
+            print(_uni)
             # Todo: Create empty budget
             return None
         self.__budget.filename = self.__filename
-        interface.readFile_send_message(utils.mapping(_("Loading file $1"),
-                         (self.__filename,)).encode("utf-8"))
+        _tuni = _("Loading file $1")
+        _uni = utils.mapping(_tuni, (self.__filename,))
+        interface.readFile_send_message(_uni)
         interface.readFile_progress(_file.tell() / _filesize)
         _buffer = _file.read(1000)
+        _dbuffer = text(_buffer, self.__character_set)
         interface.updateGui()
         # set codepage from V record
-        _record_list = _buffer.split("~")
+        _record_list = _dbuffer.split("~")
         registro_V = _record_list[1]
         # ~V|[PROPIEDAD_ARCHIVO]|VERSION_FORMATO[\DDMMAAAA]|[PROGRAMA_EMISION]|
         # [CABECERA]\{ ROTULO_IDENTIFICACION \}|[JUEGO_CARACTERES]|
@@ -2120,36 +2122,36 @@
                 # remove leading spaces
                 if _version in self.__character_sets_dict:
                     self.__character_set = self.__character_sets_dict[_version]
-                    interface.readFile_send_message(utils.mapping(
-                        _("FIEBDC character encoding: $1"),
-                          (self.__character_set,)).encode("utf8"))
+                    _tuni = _("FIEBDC character encoding: $1")
+                    _uni = utils.mapping(_tuni, (self.__character_set,))
+                    interface.readFile_send_message(_uni)
                 else:
-                    interface.readFile_send_message(utils.mapping(
-                        _("This Character encoding do not exist in "\
-                          "FIEBDC3! Default Character encoding: $1"),
-                          (self.__character_set,)).encode("utf-8"))
+                    _tuni = _("This Character encoding do not exist in "\
+                          "FIEBDC3! Default Character encoding: $1")
+                    _uni = utils.mapping(_tuni, (self.__character_set,))
+                    interface.readFile_send_message(_uni)
             else:
-                interface.readFile_send_message(utils.mapping(_(
-                         "This V record dot have a character encoding! "\
-                         "Default character encoding: $1"),
-                         (self.__character_set,)).encode("utf-8"))
+                _tuni = _("This V record dot have a character encoding! "\
+                          "Default character encoding: $1")
+                _uni = utils.mapping(_tuni, (self.__character_set,))
+                interface.readFile_send_message(_uni)
         else:
-            interface.readFile_send_message(utils.mapping(_(
-                  "Not 'V' record in File! Default character encoding: "\
-                  "$1"), (self.__character_set,)).encode("utf-8"))
-        _buffer = unicode(_buffer, self.__character_set)
+            _tuni = _("Not 'V' record in File! Default character encoding: $1")
+            _uni = utils.mapping(_tuni, (self.__character_set,))
+            interface.readFile_send_message(_uni)
+        _dbuffer = text(_buffer, self.__character_set)
         interface.updateGui()
         # Any INFORMATION between the beginning of the file and the
         # beginning of the first registry “~” is ignored
         #"after_first_tilde" : "^[^~]*~"
-        _buffer = self.__pattern["after_first_tilde"].sub("",_buffer)
-        while _buffer != u"" and not self.__cancel:
+        _dbuffer = self.__pattern["after_first_tilde"].sub("",_dbuffer)
+        while _dbuffer != "" and not self.__cancel:
             #-# the blank characters (32), tabs (9) and end of line (13 and 10)
             # before the separators '~', '|' are erased.
             # Before separator \ not deleted because it affects the reading of
             # the record ~P
-            _buffer = self.eraseControlCharacters(_buffer)
-            _record_list = _buffer.split(u"~")
+            _dbuffer = self.eraseControlCharacters(_dbuffer)
+            _record_list = _dbuffer.split("~")
             # The last record can be incomplete unless it is the last one of
             # the file
             #if len(_record_list) > 1:
@@ -2161,9 +2163,9 @@
                 # The blank characters (32), tabs (9) and end of line
                 # (13 and 10) at the end of the file are ignored.
                 #"end_control" : "((\r\n)| |\t)+$"
-                _record_list[-1] = self.__pattern["end_control"].sub(u"",
+                _record_list[-1] = self.__pattern["end_control"].sub("",
                                            _record_list[-1])
-                _last_record = u""
+                _last_record = ""
             for record in _record_list:
                 if self.__cancel:
                     break
@@ -2172,8 +2174,8 @@
             interface.readFile_progress(_file.tell() / _filesize)
             _buffer2 = _file.read(100000)
             interface.updateGui()
-            _buffer2 = unicode(_buffer2, self.__character_set)
-            _buffer = _last_record + _buffer2
+            _dbuffer2 = text(_buffer2, self.__character_set)
+            _dbuffer = _last_record + _dbuffer2
             interface.updateGui()
         _file.close()
         if self.__cancel:
@@ -2182,13 +2184,12 @@
         else:
             self.__statistics.time = time.time()-_time
             if self.__statistics.O > 0:
-                _str = utils.mapping(
-                    _("$1 unsuported record type O: Comercial Relationship"),
-                    (str(self.__statistics.O,)))
-                interface.readFile_send_message(_str.encode("utf-8"))
+                _tuni = _("$1 unsuported record type O: Comercial Relationship")
+                _uni = utils.mapping(_tuni, (text(self.__statistics.O,)))
+                interface.readFile_send_message(_uni)
             if self.__statistics.valid == 0:
-                _str = _("This file is not a valid FIBDC3 file")
-                interface.readFile_send_message(_str.encode("utf-8"))
+                _tuni = _("This file is not a valid FIBDC3 file")
+                interface.readFile_send_message(_tuni)
                 return None
             interface.readFile_end()
             self._testBudget(self.__budget, interface)
@@ -2201,7 +2202,8 @@
         Test and repair budget object after read it from bc3 file
         """
         # TODO: more to do here
-        print( _("Testing budget ...").encode("utf-8") )
+        _tuni = _("Testing budget ...")
+        print(_tuni)
         # Add price to records without price
         _iter = budget.iter()
         _titlelist = budget.getTitleList()[1]
@@ -2220,17 +2222,18 @@
                     _price = [0.0, _root.getDate(_len_prices + _index)]
                     budget.addPriceToRecord(_price,_record)
             interface.updateGui()
-        print(_("End Test").encode("utf-8"))
+        _tuni = _("End Test")
+        print(_tuni)
 
     def delete_control_space(self, text):
         text = self.delete_control(text)
-        text = text.replace(u" ", u"")
+        text = text.replace(" ", "")
         return text
 
     def delete_control(self, text):
-        text = text.replace(u"\t", u"")
-        text = text.replace(u"\r", u"")
-        text = text.replace(u"\n", u"")
+        text = text.replace("\t", "")
+        text = text.replace("\r", "")
+        text = text.replace("\n", "")
         return text
     
 class Interface(object):
@@ -2278,7 +2281,7 @@
         
         print( message )
         """
-        print( message.encode("utf-8") )
+        print(message)
 
     def readFile_progress(self, percent):
         """progress(percent)
@@ -2295,8 +2298,10 @@
         The readFile method end successfully
         """
         self.endSuccessfully == True
-        print(self.__statistics.encode("utf-8"))
-        print(("progreso = " + str(self.__progress)).encode("utf-8"))
+        print(self.__statistics)
+        _tuni = "progreso = $1"
+        _uni = utils.mapping(_tuni, (text(self.__progress,)))
+        print(_uni)
 
     def readFile_cancel(self):
         """readFile_cancel()
@@ -2304,8 +2309,11 @@
         The readFile method is canceled
         """
         self.endSuccessfully == False
-        print( _("Process terminated").encode("utf-8") )
-        print(("progreso = " + str(self.__progress)).encode("utf-8"))
+        _tuni = _("Process terminated")
+        print(_tuni)
+        _tuni = "progreso = $1"
+        _uni = utils.mapping(_tuni, (text(self.__progress,)))
+        print(_tuni)
 
     def updateGui(self):
         """updateGui(self)
@@ -2385,10 +2393,13 @@
         return self.str()
 
     def str(self):
-        _str = utils.mapping(_("Time to load: $1 seconds"),
-                (("%.2f" %(self.time)),)) + "\n" + \
-               utils.mapping(_("Records/Valid Records: $1/$2"), 
-               (str(self.records), str(self.valid))) + "\n" +\
+        _tuni1 = _("Time to load: $1 seconds")
+        _uni1 = utils.mapping(_tuni1, (("%.2f" %(self.time)),))
+        _tuni2 = _("Records/Valid Records: $1/$2")
+        _uni2 = utils.mapping(_tuni2, 
+                              (text(self.records), text(self.valid)))
+        _uni = _uni1 + "\n" + \
+               _uni2 + "\n" +\
                "V: %s\n" %(self.V,) + \
                "C: %s\n" %(self.C,) + \
                "D: %s\n" %(self.D,) + \
@@ -2410,5 +2421,5 @@
                "F: %s\n" %(self.F,) + \
                "A: %s\n" %(self.A,) + \
                "?: %s\n" %(self.unknow,)
-        return _str.encode("utf8")
+        return _uni
 
--- a/Generic/globalVars.py	Mon May 20 13:18:33 2019 +0200
+++ b/Generic/globalVars.py	Tue Jun 18 17:50:23 2019 +0200
@@ -22,12 +22,17 @@
 # module for global variables
 # not translatable strings here _("strig")
 
+# python 2/3 compatibility
+from __future__ import absolute_import, division, print_function, unicode_literals
+
 import os
 import sys
 
+
+
 name = "pyArq Presupuestos"
 version = "v0.0.0"
-changeset = "c25"
+changeset = "c26"
 baseversion = 0
 
 # path: Paths where find the program files needed
--- a/Generic/utils.py	Mon May 20 13:18:33 2019 +0200
+++ b/Generic/utils.py	Tue Jun 18 17:50:23 2019 +0200
@@ -20,14 +20,22 @@
 ## along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 # Modules
+
+# python 2/3 compatibility
+from __future__ import absolute_import, division, print_function, unicode_literals
+from builtins import str as text
+from six import text_type
+from io import IOBase
+
 import re 
 import imghdr
 import os.path
 
+
 # add svg to imghdr
 def test_svg(h, f):
     """SVG """
-    if  isinstance(f,file):
+    if  isinstance(f,IOBase):
         _pos = f.tell()
         f.seek(0)
         _h = f.read(32)
@@ -37,35 +45,35 @@
     else:
         _h = h
         _l = h[-32:]
-    if "<?xml" in _h and "</svg>" in  _l:
+    if b"<?xml" in _h and b"</svg>" in  _l:
         return 'svg'
 imghdr.tests.append(test_svg)
 
 # add ico to imghdr
 def test_ico(h, f):
     """ico image file"""
-    if h[:4] == "\x00\x00\x01\x00":
+    if h[:4] == b"\x00\x00\x01\x00":
         return 'ico'
 imghdr.tests.append(test_ico)
 
 # add wmf to imghdr
 def test_pdf(h, f):
     """pdf file"""
-    if h[:4] == "%PDF":
+    if h[:4] == b"%PDF":
         return 'pdf'
 imghdr.tests.append(test_pdf)
 
 # add wmf to imghdr
 def test_wmf(h, f):
     """wmf image library"""
-    if h[:6] == "\xd7\xcd\xc6\x9a\x00\x00":
+    if h[:6] == b"\xd7\xcd\xc6\x9a\x00\x00":
         return 'wmf'
 imghdr.tests.append(test_wmf)
 
 # add dxf to imghdr
 def test_dxf(h, f):
     """AutoCAD DXF: Drawing Interchange Format"""
-    if  isinstance(f,file):
+    if  isinstance(f,IOBase):
         _pos = f.tell()
         f.seek(0)
         _h = f.read(128)
@@ -75,16 +83,16 @@
     else:
         _h = h
         _l = h[-32:]
-    _h = _h.replace("\r","")
-    _l = _l.replace("\r","")
-    if ("  0\nSECTION\n  2\nHEADER\n" in _h or\
-       "  0\nSECTION\n  2\nCLASSES\n" in _h or\
-       "  0\nSECTION\n  2\nTABLES\n" in _h or\
-       "  0\nSECTION\n  2\nBLOCKS\n" in _h or\
-       "  0\nSECTION\n  2\nENTITIES\n" in _h or\
-       "  0\nSECTION\n  2\nOBJECTS\n" in _h or\
-       "  0\nSECTION\n  2\nTHUMBNAILIMAGE\n" in _h) and \
-       _l[-19:] == "  0\nENDSEC\n  0\nEOF\n":
+    _h = _h.replace(b"\r",b"")
+    _l = _l.replace(b"\r",b"")
+    if (b"  0\nSECTION\n  2\nHEADER\n" in _h or\
+       b"  0\nSECTION\n  2\nCLASSES\n" in _h or\
+       b"  0\nSECTION\n  2\nTABLES\n" in _h or\
+       b"  0\nSECTION\n  2\nBLOCKS\n" in _h or\
+       b"  0\nSECTION\n  2\nENTITIES\n" in _h or\
+       b"  0\nSECTION\n  2\nOBJECTS\n" in _h or\
+       b"  0\nSECTION\n  2\nTHUMBNAILIMAGE\n" in _h) and \
+       _l[-19:] == b"  0\nENDSEC\n  0\nEOF\n":
         return 'dxf'
 imghdr.tests.append(test_dxf)
 
@@ -100,8 +108,7 @@
         "Invalid type (%s) in record: %s" %(type, record)
     """
     for _index in range(len(tuple_strings)):
-        string = string.replace("$" + str(_index+1), tuple_strings[_index])
-        #string = string.replace("$" + str(_index+1), str(tuple[_index]))
+        string = string.replace("$" + text(_index+1), tuple_strings[_index])
     return string
 
 def eliminate_duplicates(list):
@@ -143,40 +150,52 @@
             code: the code or the corrected code
     """
     _is_valid = True
-    if not isinstance(code, str):
-        print("Not a string, code: " + code + type(code) )
+    if not isinstance(code, text_type):
+        _tuni = _("Not a text string, code: $1, type: $2")
+        _uni = mapping(_tuni, (code ,text(type(code))))
+        print(_uni)
         return False, False
     if code == "":
         return False, False
     try:
-        _unicode_code = unicode(code, "utf8",'replace')
-        _code_utf8 = _unicode_code.encode("utf8",'replace')
+        #_unicode_code = unicode(code, "utf-8",'replace')
+        _unicode_code = code
+        _code_utf8 = _unicode_code.encode("utf-8",'replace')
         _code_cp850 = _unicode_code.encode("cp850",'replace')
-        _unicode_code = unicode(_code_cp850, "cp850",'replace')
+        _unicode_code = text(_code_cp850, "cp850",'replace')
 
     except UnicodeError:
-        print ("Unicode Error, code: " +  code )
+        _tuni = _("Unicode Error, code: $1")
+        _uni = mapping(_tuni, (code, ))
+        print (_uni)
         return False, False
-    if _code_utf8 != code:
-        print ("Not in cp950, code: " +  code )
+    if code != _unicode_code:
+        _tuni = _("Not in cp850, code: $1")
+        _uni = mapping(_tuni, (code, ))
+        print (_uni)
         _is_valid = False
         if _code_utf8 == "":
             return False, False
         code = _code_utf8
     _code2 = re.sub("[\t \n\r~|\\\]","",code)
     if _code2 != code:
-        print("Control characters in code: " + code )
+        _tuni = _("Control characters in code: $1")
+        _uni = mapping(_tuni, (code, ))
+        print(_uni)
         if _code2 == "":
             return False, False
         _is_valid = False
         code = _code2
     if code[-1] == "#":
-        print("# in code: " + code )
-        _is_valid =  False
+        _tuni = _("# in code: $1")
+        _uni = mapping(_tuni, (code, ))
+        print(_uni)
+        _is_valid = False
         while code[-1] == "#":
             code = code[:-1]
     if code == "":
-        print("Empty code")
+        _tuni = _("Empty code")
+        print(_tuni)
         return False, False
     return _is_valid, code
 
--- a/Gtk/gui.py	Mon May 20 13:18:33 2019 +0200
+++ b/Gtk/gui.py	Tue Jun 18 17:50:23 2019 +0200
@@ -46,7 +46,26 @@
 
 # python 2/3 compatibility
 from __future__ import absolute_import, division, print_function, unicode_literals
-
+from builtins import str as text
+from six import text_type
+
+def textinp2(textstring):
+    """textinp2(textstring)
+    
+    python2 decode textstring with utf-8
+    python3 raise except and do nothing with textstring
+    
+    return textstring
+    
+    All output gtk string must be passed by textinp2
+    """
+    try:
+        # python2 works, python3 raise except and do nothing with textstring
+        textstring = text(textstring, "utf-8")
+    except TypeError:
+        pass
+    return textstring
+    
 # Standar Modules
 import sys
 import os
@@ -81,20 +100,23 @@
         _pixbufIcon = GdkPixbuf.Pixbuf.new_from_file(_icon_file)
         _pixbufIcons.append(_pixbufIcon)
     else:
-        print(utils.mapping(_("The icon file does not exist. '$1'"),
-          (str(globalVars.getAppPath(_icon)),)) )
+        _tuni = _("The icon file does not exist. '$1'")
+        _uni = utils.mapping(_tuni, (globalVars.getAppPath(_icon),))
+        print(_uni )
 if len(_pixbufIcons) > 0:
     Gtk.Window.set_default_icon_list(_pixbufIcons)
 
 else:
-    print(utils.mapping(_("The icon file does not exist. '$1'"),
-          (str(globalVars.getAppPath("ICON")),)) )
+    _tuni = _("The icon file does not exist. '$1'")
+    _uni = utils.mapping(_tuni, (globalVars.getAppPath("ICON"),))
+    print(_uni )
 
 # Autodetect desktop
 if globalVars.desktop["autodetect"]:
     openwith.autodetect_desktop()
-    print(utils.mapping(_("pyArq-Presupuestos running on $1"),
-                        (globalVars.desktop["desktop"],)))
+    _tuni = _("pyArq-Presupuestos running on $1")
+    _uni = utils.mapping(_tuni, (globalVars.desktop["desktop"],))
+    print(_uni)
 
 
 class App(Gtk.Application):
@@ -659,7 +681,9 @@
             if len(self.__page_list) == 0:
                 self._disable_navigation()
         else:
-            raise IndexError( _("The page is not in the page list") )
+            _tuni =  _("The page is not in the page list") 
+            _str = _tuni.encode("utf-8")
+            raise IndexError(_str)
 
     def _menuitemGoToRoot(self, action, parameter):
         """_menuitemGoToRoot(action, parameter)
@@ -829,9 +853,13 @@
         If the selected file has a bc3 extension 
         _launchProgressWindow is called
         """
-        _file = filename
+        _file = filename # string in python 2, unicode in python 3
         if sys.getfilesystemencoding():
-            _file = _file.decode(sys.getfilesystemencoding())
+            try:
+                # python2 works, python3 raise except and do nothing with _file
+                _file = text(filename, sys.getfilesystemencoding())
+            except TypeError:
+                pass
         self.__file = _file
         _filename = os.path.basename(self.__file)
         _filename_ext = _filename.split(".")[-1]
@@ -1008,7 +1036,7 @@
         
         Sets progress
         """
-        _progress = str(int(round(100 * percent,0)))
+        _progress = text(int(round(100 * percent,0)))
         self.__progress = percent
 
     def readFile_send_message(self, message):
@@ -1094,7 +1122,7 @@
             return False
         else:
             self.__progress_bar.set_fraction(self.__progress)
-            _text = "%s%%" %str(int(round(100 * self.__progress,0)))
+            _text = "%s%%" %text(int(round(100 * self.__progress,0)))
             self.__progress_bar.set_text(_text)
             return True
 
@@ -1460,23 +1488,27 @@
         """
         if pane_path is None:
             pane_path = (0,)
-        if not isinstance(list_paned , list):
-            raise ValueError( _("The value must be a list") )
+        if not isinstance(list_paned, list):
+            _tuni = _("The value must be a list") 
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         if list_paned[0] == "v" or  list_paned[0] == "h":
             if len(list_paned) != 3:
-                raise ValueError( _("Incorrect len") )
-            if not isinstance(list_paned[1],list):
+                _tuni = _("Incorrect len") 
+                _str = _tuni.encode("utf-8")
+                raise ValueError(_str)
+            if not isinstance(list_paned[1], list):
                 list_paned[1] = [list_paned[1]]
-            if not isinstance(list_paned[2],list):
+            if not isinstance(list_paned[2], list):
                 list_paned[2] = [list_paned[2]]
-            _item1 = self._itemsFactory(list_paned[1],pane_path + (0,))
-            _item2 = self._itemsFactory(list_paned[2],pane_path + (1,)) 
+            _item1 = self._itemsFactory(list_paned[1], pane_path + (0,))
+            _item2 = self._itemsFactory(list_paned[2], pane_path + (1,)) 
             _item = Paned(list_paned[0], pane_path, _item1, _item2)
         elif list_paned[0] == "DecompositionList":
-            _item = View( "DecompositionList", self.__budget,
+            _item = View("DecompositionList", self.__budget,
                 weakref.ref(self), pane_path, self.__active_path_record, True)
         elif list_paned[0] == "RecordDescription":
-            _item = View( "RecordDescription", self.__budget,weakref.ref(self),
+            _item = View("RecordDescription", self.__budget,weakref.ref(self),
                 pane_path, self.__active_path_record, True)
         elif list_paned[0] == "Measure":
             _item = View("Measure", self.__budget, weakref.ref(self),
@@ -1484,7 +1516,7 @@
         elif list_paned[0] == "Sheet of Conditions":
             _item  = View("Sheet of Conditions",
                           self.__budget, weakref.ref(self), pane_path,
-                self.__active_path_record)
+                          self.__active_path_record)
         elif list_paned[0] == "FileView":
             _item  = View("FileView", self.__budget, weakref.ref(self),
                           pane_path, self.__active_path_record)
@@ -1493,8 +1525,10 @@
                           pane_path, self.__active_path_record)
         else:
             _item = None
-            raise ValueError( utils.mapping(_("Incorrect item $1"),
-                  (str(list_paned[0]),)) )
+            _tuni = _("Incorrect item $1")
+            _uni = utils.mapping(_tuni, (text(list_paned[0]),))
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         return _item
 
     def _setActivePathRecord(self, path_record):
@@ -1509,8 +1543,10 @@
                 self.__active_path_record = path_record
                 self._appendHistory(path_record)
             else:
-                raise ValueError( utils.mapping(_("The budget does not have "\
-                    "the path record: $1"), (str(path_record),)) )
+                _tuni = _("The budget does not have the path record: $1")
+                _uni = utils.mapping(_tuni, (text(path_record),))
+                _str = _uni.encode("utf-8")
+                raise ValueError(_str)
 
     def _appendHistory(self, path):
         """_appendHistory(path))
@@ -1644,7 +1680,7 @@
         _code = self.budget.getCode(record_path)
         _record = self.budget.getRecord(_code)
         _summary = _record.summary
-        _text = _code.decode("utf8") + " " + _summary.decode("utf8")
+        _text = _code + " " + _summary
         if len(_text) > 30:
             _text = _text[:27] + "..."
         _icon = self._getImage(_record)
@@ -1925,8 +1961,10 @@
             _view_icon = Gtk.Image()
             _view_icon.set_from_file(globalVars.getAppPath("COMPANY-ICON"))
         else:
-            raise ValueError( _(utils.mapping("Invalid type of View: $1",
-                  view_type)) )
+            _tuni = _("Invalid type of View: $1")
+            _uni = utils.mapping(_tuni, view_type)
+            _str = _uni.encode("utf-8")
+            raise ValueError(_str)
         _view_icon.show()
         _combobox.connect("changed", self._change_combo)
         _combobox.show()
@@ -2258,7 +2296,9 @@
         self.__orientation = orientation
         if not isinstance(item1.widget, Gtk.Widget) or \
            not isinstance(item2.widget, Gtk.Widget):
-            raise ValueError( _("The item must be a widget object.") )
+            _tuni = _("The item must be a widget object.")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         if orientation == "v":
             self.__widget = Gtk.Paned.new(Gtk.Orientation(1))
             self.__widget.set_wide_handle(True) 
@@ -2266,7 +2306,9 @@
             self.__widget = Gtk.Paned.new(Gtk.Orientation(0))
             self.__widget.set_wide_handle(True) 
         else:
-            raise ValueError( _("Invalid orientation.") )
+            _tuni = _("Invalid orientation.")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         self.__widget.pack1(item1.widget,True,False)
         self.__widget.pack2(item2.widget,True,False)
         self.__widget.show()
@@ -2638,7 +2680,9 @@
         # TODO: to group all columns in a dicctionary
         # Budget
         if not isinstance(budget, base.Budget):
-            raise ValueError( _("Argument must be a Budget object") )
+            _tuni = _("Argument must be a Budget object")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         self.__budget = budget
         self.__wr_page = wr_page
         self.__pane_path = pane_path
@@ -2905,19 +2949,19 @@
             _parent_code = self.budget.getCode(self.__active_path_record[:-1])
             _parent_record = self.__budget.getRecord(_parent_code)
             _amount = _budget.getStrAmount(self.__active_path_record)
-        _str = _("Code") + chr(10) + "[" + _code.decode("utf8") + "]"
+        _str = _("Code") + chr(10) + "[" + _code + "]"
         self.__code_column.set_title(_str)
-        _str = _("Unit") + chr(10) + "[" + _unit.decode("utf8") + "]"
+        _str = _("Unit") + chr(10) + "[" + _unit + "]"
         self.__unit_column.set_title(_str)
         _str = _("Description") + chr(10) + "[" + \
-               _description.decode("utf8") + "]"
+               _description + "]"
         self.__description_column.set_title(_str)
         self.__measure_column.set_title(
             _("Measure") + chr(10) + "[" + _stryield + "]")
         self.__price_column.set_title(
             _("Price") + chr(10) + "[" + _price + "]")
         self.__amount_column.set_title(
-            _("Amount") + chr(10) + "[" + str(_amount) + "]")
+            _("Amount") + chr(10) + "[" + text(_amount) + "]")
 
     def _setListstoreValues(self, path_record):
         """_setListstoreValues(path_record)
@@ -2928,7 +2972,9 @@
         self.__liststore.clear()
         _budget = self.__budget
         if not _budget.hasPath(path_record):
-            raise ValueError( _("Invalid path") )
+            _tuni = _("Invalid path")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         else:
             _parent_code = _budget.getCode(path_record)
             for N,_code in enumerate(_budget.getchildren(_parent_code)):
@@ -2977,7 +3023,7 @@
         _number = _row_path[-1]
         _record = tree_model[_row_path][0]
         if column is self.__index_column:
-            cell_renderer.set_property('text', str(_number + 1))
+            cell_renderer.set_property('text', text(_number + 1))
             self.__index_column.get_cells()[1].set_property(
                 'cell-background', lcolor[_number % 2])
         elif column is self.__code_column:
@@ -3008,7 +3054,7 @@
             _parent_record = self.__budget.getRecord(_parent_code)
             _amount = self.budget.getStrAmount(
                         self.__active_path_record + (_number,))
-            cell_renderer.set_property('text', str(_amount))
+            cell_renderer.set_property('text', text(_amount))
         elif column is self.__type_column:
             _hierarchy = tree_model[_row_path][0].recordType.hierarchy
             _type = tree_model[_row_path][0].recordType.type
@@ -3272,7 +3318,9 @@
         if path_record is None:
             path_record = (0,)
         if not isinstance(budget, base.Budget):
-            raise ValueError( _("Argument must be a Budget object") )
+            _tuni = _("Argument must be a Budget object")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         self.__budget = budget
         self.__wr_page = page
         self.__pane_path = pane_path
@@ -3527,7 +3575,7 @@
         _measure = self.__budget.getMeasure(self.__active_path_record)
         _DS = self.__budget.getDecimals("DS")
         _total = _measure.measure
-        _total_str = ("%." + str(abs(_DS)) + "f" ) % _total
+        _total_str = ("%." + text(abs(_DS)) + "f" ) % _total
         self.columns[1].set_title(_("Type"))  # Σ parcial Σ total
         self.columns[2].set_title(_("Comment"))
         self.columns[3].set_title(_("N\n(a)"))
@@ -3547,7 +3595,9 @@
         self.__liststore.clear()
         _budget = self.__budget
         if not _budget.hasPath(path_record):
-            raise ValueError( _("Invalid path") )
+            _tuni = _("Invalid path")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         else:
             _measure = _budget.getMeasure(path_record)
             if isinstance(_measure, base.Measure):
@@ -3556,8 +3606,10 @@
                     _values = [ _line ]
                     _treeiter = self.__liststore.append(_values)
             else:
-                raise ValueError( utils.mapping(_("measure must be a Measure "\
-                      "object. Type: $1"), (str(type(_measure)),)) )
+                _tuni = _("measure must be a Measure object. Type: $1")
+                _uni = utils.mapping(_tuni, (text(type(_measure)),))
+                _str = _tuni.encode("utf-8")
+                raise ValueError(_str)
 
     def _colorCell(self, column, cell_renderer, tree_model, iter, lcolor):
         """_colorCell(column, cell_renderer, tree_model, iter, lcolor)
@@ -3587,7 +3639,7 @@
         _row_path = tree_model.get_path(iter)
         _number = _row_path[-1]
         if column is self.__index_column:
-            cell_renderer.set_property('text', str(_number + 1))
+            cell_renderer.set_property('text', text(_number + 1))
             self.__index_column.get_cells()[1].set_property(
                 'cell-background', lcolor[_number % 2])
         elif column is self.__linetype_column:
@@ -3605,35 +3657,35 @@
                         self.__calculatedline_icon)
         elif column is self.__comment_column:
             _measure = tree_model[_row_path][0]
-            _comment = str(_measure.comment)
+            _comment = text(_measure.comment)
             cell_renderer.set_property('text', _comment)
         elif column is self.__units_column:
             _measure = tree_model[_row_path][0]
             _units = _measure.units
             if isinstance(_units, float):
                 _DN = self.__budget.getDecimals("DN")
-                _units = ("%." + str(abs(_DN)) + "f" ) % _units
+                _units = ("%." + text(abs(_DN)) + "f" ) % _units
             cell_renderer.set_property('text', _units)
         elif column is self.__length_column:
             _measure = tree_model[_row_path][0]
             _length = _measure.length
             if isinstance(_length, float):
                 _DD = self.__budget.getDecimals("DD")
-                _length = ("%." + str(abs(_DD)) + "f" ) % _length
+                _length = ("%." + text(abs(_DD)) + "f" ) % _length
             cell_renderer.set_property('text', _length)
         elif column is self.__width_column:
             _measure = tree_model[_row_path][0]
             _width = _measure.width
             if isinstance(_width, float):
                 _DD = self.__budget.getDecimals("DD")
-                _width = ("%." + str(abs(_DD)) + "f" ) % _width
+                _width = ("%." + text(abs(_DD)) + "f" ) % _width
             cell_renderer.set_property('text', _width)
         elif column is self.__height_column:
             _measure = tree_model[_row_path][0]
             _height = _measure.height
             if isinstance(_height, float):
                 _DD = self.__budget.getDecimals("DD")
-                _height = ("%." + str(abs(_DD)) + "f" ) % _height
+                _height = ("%." + text(abs(_DD)) + "f" ) % _height
             cell_renderer.set_property('text', _height)
         elif column is self.__formula_column:
             _measure = tree_model[_row_path][0]
@@ -3648,7 +3700,7 @@
             else:
                 if isinstance(_parcial, float):
                     _DS = self.__budget.getDecimals("DS")
-                    _parcial = ("%." + str(abs(_DS)) + "f" ) % _parcial
+                    _parcial = ("%." + text(abs(_DS)) + "f" ) % _parcial
             cell_renderer.set_property('text', _parcial)
         elif column is self.__subtotal_column:
             _measure_line = tree_model[_row_path][0]
@@ -3663,7 +3715,7 @@
                 lcolor = [_color, _color]
                 if isinstance(_subtotal, float):
                     _DS = self.__budget.getDecimals("DS")
-                    _subtotal= ("%." + str(abs(_DS)) + "f" ) % _subtotal
+                    _subtotal= ("%." + text(abs(_DS)) + "f" ) % _subtotal
                 cell_renderer.set_property('text', _subtotal)
             else:
                 cell_renderer.set_property('text', "")
@@ -3854,9 +3906,10 @@
         _textview.show()
         _vbox = Gtk.Grid()
         _vbox.set_orientation(Gtk.Orientation(1)) # 1 Vertical
-        self.__label = Gtk.Label(utils.mapping(_("Description text of the "\
-                     "record $1"), (str(self.__budget.getCode(
-                    self.__active_path_record)),)))
+        _tuni = _("Description text of the record $1")
+        _ucode = self.__budget.getCode(self.__active_path_record)
+        _uni = utils.mapping(_tuni, (_ucode,))
+        self.__label = Gtk.Label(_uni)
         self.__label.set_alignment(0, 0)
         self.__label.show()
         _vbox.add(self.__label)
@@ -3875,8 +3928,9 @@
         _budget = self.__budget
         self.__active_path_record = path_record
         _code = _budget.getCode(self.__active_path_record)
-        self.__label.set_text(utils.mapping(_("Description text of the record "\
-            "$1"), (_code.decode("utf8"),)))
+        _tuni = _("Description text of the record $1")
+        _uni = utils.mapping(_tuni, (_code,))
+        self.__label.set_text(_uni)
         _text = _budget.getRecord(_code).text
         self.__textbuffer.set_text(_text)
 
@@ -4029,9 +4083,10 @@
         _budget = budget
         _main_box = Gtk.Grid()
         _main_box.set_orientation(Gtk.Orientation(1)) # 1 Vertical
-        self.__label = Gtk.Label(utils.mapping(_("Sheet of Conditions of the "\
-                       "record $1"), (self.__budget.getCode(
-                       self.__active_path_record),)))
+        _tuni = _("Sheet of Conditions of the record $1")
+        _ucode = self.__budget.getCode(self.__active_path_record)
+        _uni = utils.mapping(_tuni, (_ucode,))
+        self.__label = Gtk.Label(_uni)
         self.__label.set_xalign(0)
         self.__label.set_yalign(0)
         self.__label.show()
@@ -4237,8 +4292,9 @@
         _budget = self.__budget
         self.__active_path_record = path_record
         _code = _budget.getCode(self.__active_path_record)
-        self.__label.set_text(utils.mapping(_("Sheet2 of Conditions of the "\
-                     "record $1"), (_code,)))
+        _tuni = _("Sheet2 of Conditions of the record $1")
+        _uni = utils.mapping(_tuni, (_code,))
+        self.__label.set_text(_uni)
         self._setFields()
 
     def runMessage(self, message, pane_path, arg=None):
@@ -4697,7 +4753,9 @@
         self.__selection = None
         # Seting init args
         if not isinstance(budget, base.Budget):
-            raise ValueError( _("Argument must be a Budget object") )
+            _tuni = _("Argument must be a Budget object")
+            _str = _tuni.encode("utf-8")
+            raise ValueError(_str)
         self.__budget = budget
         self.__wr_page = wr_page
         self.__pane_path = pane_path
@@ -4836,12 +4894,14 @@
         if len(path) == 1:
             # The selection is a company
             _company_key = self.__treestore[path][0]
+            _company_key = textinp2(_company_key)
             _company = self.__budget.getCompany(_company_key)
             _selection = "company"
             _values = _company.values
         else:
             # The selection is a office
             _company_key = self.__treestore[path[:1]][0]
+            _company_key = textinp2(_company_key)
             _company = self.__budget.getCompany(_company_key)
             _selection = "office"
             _office = _company.offices[path[1]]
@@ -4877,7 +4937,7 @@
         if message == "change_active":
             if _budget.hasPath(arg):
                 _path_record = arg
-                self._showMessageRecord( _path_record)
+                self._showMessageRecord(_path_record)
             pass
         elif message == "clear":
             self._clear()
@@ -4910,7 +4970,7 @@
         _row_path = tree_model.get_path(iter)
         _number = _row_path[-1]
         if column is self.__index_column:
-            cell_renderer.set_property('text', str(_number + 1))
+            cell_renderer.set_property('text', text(_number + 1))
             self.__index_column.get_cells()[1].set_property(
                 'cell-background', lcolor[_number % 2])
         if self.__treeview.get_cursor() == (_row_path,column):
@@ -5271,11 +5331,8 @@
                     _option_name = _option[1]
                     _option_type = _option[2]
                     _option_description = _option[3]
-                    #-# str and unicode
-                    if (isinstance(_option_key, str) or \
-                        isinstance(_option_key, unicode)) and \
-                       (isinstance(_option_name, str) or\
-                       isinstance(_option_name, unicode))and \
+                    if isinstance(_option_key, text_type) and \
+                       isinstance(_option_name, text_type) and \
                        _option_type in self.__option_types.keys():
                         self.__liststore.append([_option_key, _option_name, "",
                             _option_type, _option_description])
@@ -5297,7 +5354,7 @@
         Sets the Options values
         """
         if isinstance(values, dict):
-            for _option, _value in values.iteritems():
+            for (_option, _value) in values.items():
                 if _option in self.__option_dict:
                     _type = self.__option_dict[_option][2]
                     if _type == "boolean":
@@ -5319,7 +5376,7 @@
                             self.__liststore.set_value(_iter, 2, _value)
                             self.__option_dict[_option][1] = _value
                     elif _type == "string":
-                        if isinstance(_value, str):
+                        if isinstance(_value, text_type):
                             _num = self.__option_list.index(_option)
                             _iter = self.__liststore.get_iter((_num,))
                             self.__liststore.set_value(_iter, 2, _value)
@@ -5340,7 +5397,7 @@
                         else:
                             print(_("Icorrect type, must be list") )
                     elif _type == "color":
-                        if isinstance(_value, str):
+                        if isinstance(_value, text_type):
                             if Gdk.RGBA().parse(_value):
                                 print(_("Icorrect type, must be a parseable " \
                                         "color") )
Binary file mo/es/LC_MESSAGES/pyArq-Presupuestos.mo has changed
--- a/mo/pyArq-Presupuestos.es.po	Mon May 20 13:18:33 2019 +0200
+++ b/mo/pyArq-Presupuestos.es.po	Tue Jun 18 17:50:23 2019 +0200
@@ -11,7 +11,7 @@
 msgstr ""
 "Project-Id-Version: pyArq-Presupuestos 0.0.0\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-04-27 10:53+0200\n"
+"POT-Creation-Date: 2019-06-18 11:57+0200\n"
 "PO-Revision-Date: 2019-04-27 10:53+0200\n"
 "Last-Translator: Miguel Ángel Bárcena Rodríguez <miguelangel@obraencurso."
 "es>\n"
@@ -21,7 +21,7 @@
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: ../Generic/base.py:283
+#: ../Generic/base.py:285
 msgid ""
 "\n"
 "A free program of measurements, budgets and control of construction sites.\n"
@@ -32,7 +32,7 @@
 "construcción.\n"
 "En estado beta de desarrollo, aún no hay una versión plenamente funcional.\n"
 
-#: ../Generic/base.py:288
+#: ../Generic/base.py:290
 msgid ""
 "\n"
 "Usage:\n"
@@ -48,291 +48,286 @@
 "Opciones de ayuda:\n"
 "    -h, --help     Muestra esta ayuda\n"
 
-#: ../Generic/base.py:421
+#: ../Generic/base.py:423
 msgid "Invalid code: $1"
 msgstr "Código no válido: $1"
 
-#: ../Generic/base.py:436
+#: ../Generic/base.py:440
 msgid "Synonyms ($1) must be a list, code: $2"
 msgstr "«Synonyms» ($1) debe ser una lista, código: $2"
 
-#: ../Generic/base.py:440
+#: ../Generic/base.py:446
 msgid "Invalid Code in synomyms list ($1) code: $2"
 msgstr "Código no válido es la lista de sinónimos ($1) código: $2"
 
-#: ../Generic/base.py:471
-msgid "Unit ($1) must be a string: $2"
-msgstr "«Unit» ($1) debe ser una cadena: $2"
+#: ../Generic/base.py:479
+msgid "Unit ($1) must be a text string: $2"
+msgstr "«Unit» ($1) debe ser una cadena de texto: $2"
 
-#: ../Generic/base.py:485
-msgid "Summary ($1) must be a string: $1"
-msgstr "«Summary» ($1) debe ser una cadena: $1"
+#: ../Generic/base.py:495
+msgid "Summary ($1) must be a text string: $1"
+msgstr "«Summary» ($1) debe ser una cadena de texto: $1"
 
-#: ../Generic/base.py:502
+#: ../Generic/base.py:514
 msgid "Prices ($1) must be a list: $2"
 msgstr "«Prices» ($1) debe ser una lista: $2"
 
-#: ../Generic/base.py:523
+#: ../Generic/base.py:537
 msgid "Price ($1) must be a list with two items: $2"
 msgstr "«Price» ($1) debe ser una lista con dos elementos: $2"
 
-#: ../Generic/base.py:528
-msgid "Price must be a float number: $1"
-msgstr "Precio debe ser un número de coma flotante: $1"
+#: ../Generic/base.py:556
+msgid "The record do not have this Price. Code: $1"
+msgstr "El registro no tiene ese precio. Código: $1"
 
-#: ../Generic/base.py:538
-#, python-format
-msgid "The record do not have this Price. Code: %s"
-msgstr "El registro no tiene ese precio. Código: %s"
-
-#: ../Generic/base.py:544
+#: ../Generic/base.py:564
 msgid "The record do not have this Price"
 msgstr "El registro no tiene ese precio"
 
-#: ../Generic/base.py:559
+#: ../Generic/base.py:581
 msgid "Parents ($1) must be a list: $2"
 msgstr "«Parents» ($1) debe ser una lista: $2"
 
-#: ../Generic/base.py:563 ../Generic/base.py:575
+#: ../Generic/base.py:587 ../Generic/base.py:601
 msgid "Invalid parent code ($1) in the record: $2"
 msgstr "Código padre no válido ($1) en el registro: $2"
 
-#: ../Generic/base.py:591
+#: ../Generic/base.py:619
 msgid "children ($1) must be a list, record: $2"
 msgstr "«children» ($1) debe ser una lista, registro: $2"
 
-#: ../Generic/base.py:595
+#: ../Generic/base.py:625
 msgid "child ($1) must be a Decomposition object, record: $2"
 msgstr "«child» ($1) debe ser una objeto «Decomposition», registro $2"
 
-#: ../Generic/base.py:649
-msgid "Text ($1) must be a string, record: $2"
-msgstr "«Text» ($1) debe ser una cadena, registro: $2"
+#: ../Generic/base.py:680
+msgid "Text ($1) must be a text string, record: $2"
+msgstr "«Text» ($1) debe ser una cadena de texto, registro: $2"
 
-#: ../Generic/base.py:662
+#: ../Generic/base.py:695
 msgid "sheet must be a Sheet instance"
 msgstr "«sheet» debe ser una instancia de Sheet"
 
-#: ../Generic/base.py:674
+#: ../Generic/base.py:709
 msgid "files must be a list: $1"
 msgstr "«files» debe ser una lista: $1"
 
-#: ../Generic/base.py:685 ../Generic/base.py:699
+#: ../Generic/base.py:722 ../Generic/base.py:740
 msgid "Incorrect path"
 msgstr "Ruta incorrecta"
 
-#: ../Generic/base.py:690
+#: ../Generic/base.py:728
 msgid "file must be a list or a File object: $1"
 msgstr "«file» debe ser una lista o un objeto «File: $1"
 
-#: ../Generic/base.py:718
+#: ../Generic/base.py:761
 msgid "labels must be a list"
 msgstr "«labels» debe ser una lista"
 
-#: ../Generic/base.py:724
-msgid "label must be a string"
+#: ../Generic/base.py:769
+msgid "label must be a text string"
 msgstr "«label» debe ser una cadena de texto."
 
-#: ../Generic/base.py:733
-msgid "Label must be a string"
+#: ../Generic/base.py:780
+msgid "Label must be a text string"
 msgstr "«Label» debe ser una cadena de texto."
 
-#: ../Generic/base.py:981
+#: ../Generic/base.py:1030
 msgid "Position must be a integer"
 msgstr "«Position» debe ser un número entero"
 
-#: ../Generic/base.py:995
+#: ../Generic/base.py:1046
 msgid "BudgetMeasures atribute must be a list"
 msgstr "El atributo «BudgetMeasures» debe ser una lista"
 
-#: ../Generic/base.py:998
-msgid "BudgetMeasures item must be a Measure "
-msgstr "El atributo «BudgetMeasures» debe ser un objeto «Measure»"
+#: ../Generic/base.py:1051
+msgid "BudgetMeasures item must be a Measure object"
+msgstr "El elemento «BudgetMeasures» debe ser un objeto «Measure»"
 
-#: ../Generic/base.py:1007
+#: ../Generic/base.py:1061
 msgid "Certification atribute must be a list or None"
 msgstr "El atributo «Certification» debe ser una lista o «None»"
 
-#: ../Generic/base.py:1015
+#: ../Generic/base.py:1071
 msgid "Real cost atribute must be a list or None"
 msgstr "El atributo «Real cost» debe ser una lista o «None»"
 
-#: ../Generic/base.py:1023
+#: ../Generic/base.py:1081
 msgid "Cost goals atribute must be a list or None"
 msgstr "El atributo «Cost goals» debe ser una lista o «None»"
 
-#: ../Generic/base.py:1031
+#: ../Generic/base.py:1091
 msgid "Cost Planned atribute must be a list or None"
 msgstr "El atributo «Cost Planned» debe ser una lista o «None»"
 
-#: ../Generic/base.py:1124
+#: ../Generic/base.py:1186
 msgid "Measure must be a float number. Type: $1"
 msgstr "«Measure» debe ser un número de coma flotante. Tipo: $1"
 
-#: ../Generic/base.py:1136
+#: ../Generic/base.py:1200
 msgid "Lines must be a list"
 msgstr "«Lines» debe ser una lista"
 
-#: ../Generic/base.py:1139
+#: ../Generic/base.py:1205
 msgid "Line must be a MeasureLine objetc"
 msgstr "«Line» debe ser un objeto «MeasureLine»"
 
-#: ../Generic/base.py:1150
+#: ../Generic/base.py:1218
 msgid "Factor must be a float number |$1|"
 msgstr "«Factor» debe ser un número de coma flotante |$1|"
 
-#: ../Generic/base.py:1162
+#: ../Generic/base.py:1232
 msgid "Yield must be a float number"
 msgstr "«Yield» debe ser un número de coma flotante"
 
-#: ../Generic/base.py:1173
+#: ../Generic/base.py:1245
 msgid "Fixed must be boolean object"
 msgstr "«Fixed» debe ser un objeto booleano"
 
-#: ../Generic/base.py:1243
+#: ../Generic/base.py:1317
 msgid "Type must be M or A. Type: $1"
 msgstr "«Type» debe ser M o A. Type: $1"
 
-#: ../Generic/base.py:1387
-msgid " Parcial Subtotal must be a float number. Parcial: $1"
+#: ../Generic/base.py:1463
+msgid "Parcial Subtotal must be a float number. Parcial: $1"
 msgstr "«Parcial Subtotal» debe ser un número de coma flotante. Parcial: $1"
 
-#: ../Generic/base.py:1395
-msgid " Acumulated Subtotal must be a float number. Parcial: $1"
+#: ../Generic/base.py:1473
+msgid "Acumulated Subtotal must be a float number. Parcial: $1"
 msgstr " «Acumulate Subtotal» debe ser un número de coma flotante. Parcial: $1"
 
-#: ../Generic/base.py:1431
+#: ../Generic/base.py:1510
 msgid "Invalid measure line type ($1)"
 msgstr "Tipo de línea de medición no válido ($1)"
 
-#: ../Generic/base.py:1437
-msgid "Measure Comment must be a string ($1)"
-msgstr "El comentario de la medición debe ser una cadena ($1)"
-
-#: ../Generic/base.py:1444
+#: ../Generic/base.py:1527
 msgid "Invalid Measure Units ($1)"
 msgstr "Unidades de medición no válidas ($1)"
 
-#: ../Generic/base.py:1457
+#: ../Generic/base.py:1542
 msgid "Invalid Measure length ($1)"
 msgstr "Longitud de medición no válida ($1)"
 
-#: ../Generic/base.py:1470
+#: ../Generic/base.py:1557
 msgid "Invalid Measure Width ($1)"
 msgstr "Anchura de medición no válida ($1)"
 
-#: ../Generic/base.py:1483
+#: ../Generic/base.py:1572
 msgid "Invalid Measure Height ($1)"
 msgstr "Altura de medición no válida ($1)"
 
-#: ../Generic/base.py:1495
-msgid "Formula must be a string ($1)"
+#: ../Generic/base.py:1586
+msgid "Formula must be a text string ($1)"
 msgstr "«Formula» debe ser una cadena de texto ($1)"
 
-#: ../Generic/base.py:1498
-msgid "There is invalid charactersin formula ($1)"
+#: ../Generic/base.py:1591
+msgid "There is invalid characters in formula ($1)"
 msgstr "Hay caracteres no válidos en la fórmula ($1)"
 
-#: ../Generic/base.py:1564 ../Generic/base.py:2618
+#: ../Generic/base.py:1659 ../Generic/base.py:2776
 msgid "'a' value must be a float number"
 msgstr "El valor «a» debe ser un número de coma flotante"
 
-#: ../Generic/base.py:1568 ../Generic/base.py:2622
+#: ../Generic/base.py:1665 ../Generic/base.py:2782
 msgid "'b' value must be a float number"
 msgstr "El valor «b» debe ser un número de coma flotante"
 
-#: ../Generic/base.py:1572 ../Generic/base.py:2626
+#: ../Generic/base.py:1671 ../Generic/base.py:2788
 msgid "'c' value must be a float number"
 msgstr "El valor «c» debe ser un número de coma flotante"
 
-#: ../Generic/base.py:1576 ../Generic/base.py:2630
+#: ../Generic/base.py:1677 ../Generic/base.py:2794
 msgid "'d' value must be a float number"
 msgstr "El valor «d» debe ser un número de coma flotante"
 
-#: ../Generic/base.py:1604 ../Generic/base.py:2658
+#: ../Generic/base.py:1707 ../Generic/base.py:2824
 msgid "Invalid formula"
 msgstr "Fórmula no válida"
 
-#: ../Generic/base.py:1858
+#: ../Generic/base.py:1963
 msgid "sheet_dict must be a dictionay"
 msgstr "«sheet_dict» debe ser un diccionario."
 
-#: ../Generic/base.py:1879 ../Generic/base.py:1886
-msgid "sheet field must be a string"
+#: ../Generic/base.py:1986 ../Generic/base.py:1997
+msgid "sheet field must be a text string"
 msgstr "«sheet field» debe ser una cadena de texto"
 
-#: ../Generic/base.py:1881
+#: ../Generic/base.py:1990
 msgid "section_dict must be a dictionary"
 msgstr "«section_dict» debe ser un dicionario"
 
-#: ../Generic/base.py:1888
-msgid "sheet section must be a string"
+#: ../Generic/base.py:2001
+msgid "sheet section must be a text string"
 msgstr "La seccion del pliego debe ser una cadena de texto"
 
-#: ../Generic/base.py:1890
-msgid "sheet paragraph must be a string"
+#: ../Generic/base.py:2005
+msgid "sheet paragraph must be a text string"
 msgstr "«sheet paragraph» debe ser una cadena de texto"
 
-#: ../Generic/base.py:2177
-msgid "Owner must be a string"
+#: ../Generic/base.py:2295
+msgid "Owner must be a text string"
 msgstr "«Owner» debe ser una cadena de texto."
 
-#: ../Generic/base.py:2193
+#: ../Generic/base.py:2313
 msgid "Invalid Date: $1"
 msgstr "Fecha no válida: $1"
 
-#: ../Generic/base.py:2204
-msgid "Comment must be a string"
-msgstr "«Comment» debe ser una cadena"
+#: ../Generic/base.py:2327
+msgid "Comment must be a text string"
+msgstr "«Comment» debe ser una cadena de texto"
 
-#: ../Generic/base.py:2220
+#: ../Generic/base.py:2345
 msgid "Budget type must be 1, 2, 3 or 4."
 msgstr "El tipo de presupuesto debe ser 1, 2, 3 o 4"
 
-#: ../Generic/base.py:2232
+#: ../Generic/base.py:2359
 msgid "Certificate order must be a integer."
 msgstr "«Certificate order» debe ser un número entero"
 
-#: ../Generic/base.py:2247
+#: ../Generic/base.py:2376
 msgid "Budget certificate Date must be a valid Date."
 msgstr "«Budget certificate Date» debe ser una fecha válida"
 
-#: ../Generic/base.py:2261
+#: ../Generic/base.py:2392
 msgid "Invalid title list format"
 msgstr "Formato de lista de rótulos no válida"
 
-#: ../Generic/base.py:2290
+#: ../Generic/base.py:2423
 msgid "Invalid Index Title"
 msgstr "Índice de rótulo no válido"
 
-#: ../Generic/base.py:2327
+#: ../Generic/base.py:2462
 msgid "Decimal Key error"
 msgstr "Clave de decimales errónea"
 
-#: ../Generic/base.py:2365
+#: ../Generic/base.py:2500
 msgid "Invalid Percentage key"
 msgstr "Clave de porcentajes no válida"
 
-#: ../Generic/base.py:2488
+#: ../Generic/base.py:2619
+msgid "No-estructured measures. Adding root record"
+msgstr "Mediciones no estructuradas. Añadiendo registro raiz"
+
+#: ../Generic/base.py:2624
 msgid "Invalid parent code: $1"
 msgstr "Código del padre inválido: $1"
 
-#: ../Generic/base.py:2491
+#: ../Generic/base.py:2629
 msgid "Invalid child code: $1 $2"
 msgstr "Código de hijo inválido: $1 $2"
 
-#: ../Generic/base.py:2494
-msgid "Invalid position in measure $1, in code $2"
+#: ../Generic/base.py:2634
+msgid "Invalid position in measure $1, in code $2 $3"
 msgstr "Posición no válida en medición $1, en código $2"
 
-#: ../Generic/base.py:2502
+#: ../Generic/base.py:2644
 msgid ""
 "Circular Decomposition, parent code: $1, child code: $2, repeated code: $3"
 msgstr ""
 "Descomposición circular, código padre: $1, código hijo: $2, código repetido: "
 "$3"
 
-#: ../Generic/base.py:2527
+#: ../Generic/base.py:2671
 msgid ""
 "No-estructured measure or empty position. Parent Code: $1, Child code: $2, "
 "Position: $3"
@@ -340,7 +335,7 @@
 "Mediciones no estructuradas o posicion vácia. Código padre: $1, Código hijo: "
 "$2, Posición: $3"
 
-#: ../Generic/base.py:2531
+#: ../Generic/base.py:2678
 msgid ""
 "No-estructured measure or empty position. Repeated child in unspecified "
 "position. It is impossible to determine the position. New child is added in "
@@ -350,7 +345,7 @@
 "posición. Es imposible determinar la posición. Se añade un nuevo hijo en la "
 "descomposicón. Código padre: $1, Código hijo: $2, Posición: $3"
 
-#: ../Generic/base.py:2571 ../Generic/base.py:2583
+#: ../Generic/base.py:2721 ../Generic/base.py:2738
 msgid ""
 "Error: Invalid child position in decomposition. Parent code: $1 Child code: "
 "$2 Position: $3"
@@ -358,84 +353,84 @@
 "Error: Posición del hijo no válida en descomposición. Código padre: $1 "
 "Código hijo: $2 Posición: $3"
 
-#: ../Generic/base.py:2577
+#: ../Generic/base.py:2730
 msgid "Error: Empty child code. Parent code: $1 Position: $2"
 msgstr "Error: Código hijo vacío. Código padre: $1 Posición: $2"
 
-#: ../Generic/base.py:2669
+#: ../Generic/base.py:2837
 msgid "Invalid code"
 msgstr "Código no válido"
 
-#: ../Generic/base.py:2679
+#: ../Generic/base.py:2849
 msgid "Invalid record: $1"
 msgstr "Registro no válido: $1"
 
-#: ../Generic/base.py:2742
+#: ../Generic/base.py:2915
 msgid "Only can be one root record"
 msgstr "Sólo puede haber un registro raíz"
 
-#: ../Generic/base.py:2851 ../Generic/base.py:2857
+#: ../Generic/base.py:3026 ../Generic/base.py:3036
 msgid "This record does not exits"
 msgstr "Este registro no existe"
 
-#: ../Generic/base.py:2854
+#: ../Generic/base.py:3031
 msgid "Path item must be a integer"
 msgstr "El elemento de la ruta debe ser un número entero"
 
-#: ../Generic/base.py:2859
+#: ../Generic/base.py:3040
 msgid "Path must be a not empty tuple: $1"
 msgstr "«Path» debe ser una tupla no vacía: $1"
 
-#: ../Generic/base.py:2926
-msgid "The sheet code must be a string"
+#: ../Generic/base.py:3108
+msgid "The sheet code must be a text string"
 msgstr "El código del pliego debe ser una cadena de texto"
 
-#: ../Generic/base.py:2928
-msgid "The sheet title must be a string"
+#: ../Generic/base.py:3112
+msgid "The sheet title must be a text string"
 msgstr "El título del pliego debe ser una cadena de texto."
 
-#: ../Generic/base.py:2939
+#: ../Generic/base.py:3125
 msgid "The sheet sections must be a dictionary"
 msgstr "La sección del pliego debe ser un dicionario"
 
-#: ../Generic/base.py:2945
-msgid "The field code must be a string"
+#: ../Generic/base.py:3133
+msgid "The field code must be a text string"
 msgstr "El código del ámbito debe ser una cadena de texto"
 
-#: ../Generic/base.py:2947
-msgid "The field title must be a string"
+#: ../Generic/base.py:3137
+msgid "The field title must be a text string"
 msgstr "El título del ámbito debe ser una cadena de texto."
 
-#: ../Generic/base.py:2958
+#: ../Generic/base.py:3150
 msgid "The sheet field must be a dictionary"
 msgstr "El ámbito del pliego debe ser un dicionario."
 
-#: ../Generic/base.py:2964
-msgid "The paragraph code must be a string"
+#: ../Generic/base.py:3158
+msgid "The paragraph code must be a text string"
 msgstr "El código del parrafo debe ser una cadena de texto."
 
-#: ../Generic/base.py:2966
-msgid "The paragraph text must be a string"
+#: ../Generic/base.py:3162
+msgid "The paragraph text must be a text string"
 msgstr "El texto del parrafo debe ser una cadena de texto"
 
-#: ../Generic/base.py:2977
+#: ../Generic/base.py:3175
 msgid "The paragraph dict must be a dictionary"
 msgstr "El dicionario del parrafo debe ser un diccionario"
 
-#: ../Generic/base.py:2983 ../Generic/base.py:3008 ../Generic/base.py:3147
-#: ../Generic/base.py:3171 ../Generic/base.py:3193
-msgid "The record_code code must be a string"
+#: ../Generic/base.py:3184 ../Generic/base.py:3217 ../Generic/base.py:3385
+#: ../Generic/base.py:3414 ../Generic/base.py:3442
+msgid "The record_code code must be a text string"
 msgstr "«record_code» debe ser una cadena de texto"
 
-#: ../Generic/base.py:2985
-msgid "The field must be a string"
+#: ../Generic/base.py:3188
+msgid "The field must be a text string"
 msgstr "El ámbito debe ser una cadena de texto."
 
-#: ../Generic/base.py:2987
+#: ../Generic/base.py:3192
 msgid "The section dict must be a dictionary"
 msgstr "El dicionario de la seccion debe ser un dicionario."
 
-#: ../Generic/base.py:2991
+#: ../Generic/base.py:3198
 msgid ""
 "Error: The budget do not have this record code and can not be added the "
 "sheet text in the field $1. Record Code: $2"
@@ -443,11 +438,11 @@
 "Error: El presupuesto no tiene ese código de registro y no puede añadirse el "
 "texto del pliego en el ámbito $1. Código del registro: $2"
 
-#: ../Generic/base.py:3011
-msgid "The filename must be a string"
+#: ../Generic/base.py:3221
+msgid "The filename must be a text string"
 msgstr "El nombre del fichero debe ser una cadena de texto."
 
-#: ../Generic/base.py:3015
+#: ../Generic/base.py:3226
 msgid ""
 "Error: The budget do not have the record code $1 and can not be added the "
 "file: $2"
@@ -455,67 +450,63 @@
 "Error: El presupuesto no tiene el código de registro $1 y no puede añadirse "
 "el fichero: $2"
 
-#: ../Generic/base.py:3026
-msgid "The company code must be a string"
+#: ../Generic/base.py:3237
+msgid "The company code must be a text string"
 msgstr "El código de la entidad debe ser una cadena de texto."
 
-#: ../Generic/base.py:3028
-msgid "The summary must be a string"
-msgstr "El resumen debe ser una cadena de texto"
-
-#: ../Generic/base.py:3030 ../Generic/base.py:3058
-msgid "The name must be a string"
+#: ../Generic/base.py:3245 ../Generic/base.py:3283
+msgid "The name must be a text string"
 msgstr "El nombre debe ser una cadena de texto."
 
-#: ../Generic/base.py:3032
+#: ../Generic/base.py:3249
 msgid "The name must be a list"
 msgstr "El nombre debe ser una lista"
 
-#: ../Generic/base.py:3036
+#: ../Generic/base.py:3255
 msgid "The office must be a list"
 msgstr "«The office» debe ser una lista"
 
-#: ../Generic/base.py:3038
+#: ../Generic/base.py:3259
 msgid "The office must be a 10 items list"
 msgstr "«The office» debe ser una lista de 10 elementos"
 
-#: ../Generic/base.py:3041
-msgid "This office item must be a string"
+#: ../Generic/base.py:3264
+msgid "This office item must be a text string"
 msgstr "El elemento de la oficina debe ser una cadena de texto."
 
-#: ../Generic/base.py:3045
+#: ../Generic/base.py:3269
 msgid "This office item must be a list"
 msgstr "Este elemento de la oficina debe ser una lista"
 
-#: ../Generic/base.py:3060
-msgid "The web must be a string"
+#: ../Generic/base.py:3287
+msgid "The web must be a text string"
 msgstr "La web debe ser una cadena de texto."
 
-#: ../Generic/base.py:3062
-msgid "The email must be a string"
+#: ../Generic/base.py:3291
+msgid "The email must be a text string"
 msgstr "El email debe ser una cadena de texto."
 
-#: ../Generic/base.py:3074
-msgid "The tecnical info code must be a string"
+#: ../Generic/base.py:3305
+msgid "The tecnical info code must be a text string"
 msgstr "La información técnica debe ser una cadena de texto."
 
-#: ../Generic/base.py:3076
-msgid "The tecnical info description must be a string"
+#: ../Generic/base.py:3309
+msgid "The tecnical info description must be a text string"
 msgstr "La descripción de la información técnica debe ser una cadena de texto"
 
-#: ../Generic/base.py:3079
-msgid "The tecnical info unit must be a string"
+#: ../Generic/base.py:3313
+msgid "The tecnical info unit must be a text string"
 msgstr "La unidad de la información técnica debe ser una cadena de texto."
 
-#: ../Generic/base.py:3130
-msgid "The label must be a string"
+#: ../Generic/base.py:3366
+msgid "The label must be a text string"
 msgstr "La etiqueta debe ser una cadena de texto."
 
-#: ../Generic/base.py:3149
-msgid "The parametric select comment must be a string"
+#: ../Generic/base.py:3389
+msgid "The parametric select comment must be a text string"
 msgstr "El comentario de selección paramétrico debe ser una cadena de texto"
 
-#: ../Generic/base.py:3152
+#: ../Generic/base.py:3393
 msgid ""
 "Error: The budget do not have the record code $1 and can not be added the "
 "Parametric select comment: $2"
@@ -523,7 +514,7 @@
 "Error: El presupuesto no tiene el código de registro $1 y no puede añadirse "
 "el comentario de selección paramétrico: $2"
 
-#: ../Generic/base.py:3159
+#: ../Generic/base.py:3401
 msgid ""
 "Error: The Record $1 is not a Parametric Record and can not have Parametric "
 "comment"
@@ -531,11 +522,11 @@
 "Error: El registro $1 no es un registro paramétrico y no puede tener "
 "comentario paramétrico."
 
-#: ../Generic/base.py:3173
-msgid "The summary record must be a string"
+#: ../Generic/base.py:3418
+msgid "The summary record must be a text string"
 msgstr "El resumen del registro debe ser una cadena de texto"
 
-#: ../Generic/base.py:3175
+#: ../Generic/base.py:3422
 msgid ""
 "Error: The budget do not have the record code $1 and can not be seted the "
 "summary: $2"
@@ -543,7 +534,7 @@
 "Error: El presupuesto no tiene el codigo de registro $1 y no puede fijarse "
 "el resumen: $2"
 
-#: ../Generic/base.py:3181
+#: ../Generic/base.py:3429
 msgid ""
 "Error: The Record $1 is not a Parametric Record and can not have Parametric "
 "summary"
@@ -551,11 +542,11 @@
 "Error: El registro $1 no es un registro paramétrico y no puede tener resumen "
 "paramétrico."
 
-#: ../Generic/base.py:3195
-msgid "The text record must be a string"
+#: ../Generic/base.py:3446
+msgid "The text record must be a text string"
 msgstr "El texto del registro debe ser una cadena de texto"
 
-#: ../Generic/base.py:3197
+#: ../Generic/base.py:3450
 msgid ""
 "Error: The budget do not have the record code $1 and can not be seted the "
 "text: $2"
@@ -563,7 +554,7 @@
 "Error: El presupuesto no tiene el codigo de registro $1 y no puede fijarse "
 "el texto: $2"
 
-#: ../Generic/base.py:3203
+#: ../Generic/base.py:3457
 msgid ""
 "Error: The Record $1 is not a Parametric Record and can not have Parametric "
 "text"
@@ -571,15 +562,19 @@
 "Error: El registro $1 no es un registro paramétrico y no puede tener texto "
 "paramétrico."
 
-#: ../Generic/base.py:3726
+#: ../Generic/base.py:3981
 msgid "Invalid Hierarchy ($1) The hierarchy must be -1, 0, 1, 2"
 msgstr "Categoría no válida ($1) La categoria debe ser -1, 0, 1 or 2"
 
-#: ../Generic/base.py:3738
+#: ../Generic/base.py:3987
+msgid "Hierarchy temporarily set to an empty string"
+msgstr ""
+
+#: ../Generic/base.py:3997
 msgid "Invalid type ($1),the type must be (empty string,0,1,2,3)"
 msgstr "Tipo no válido ($1), el tipo debe ser (cadena vacía, 0, 1, 2, 3)"
 
-#: ../Generic/base.py:3749
+#: ../Generic/base.py:4011
 msgid ""
 "Invalid subtype ($1), The subtype must one in (empty string, EA, EU, EC, EF, "
 "OB, PA, PU, H, Q, %, MC, MCr, MM, MS, ME, MCu, MAl, ML, M)"
@@ -587,28 +582,28 @@
 "Subtipo no válido ($1), el subtipo debe ser uno de (cadena vacía, EA, EU, "
 "EC, EF, OB, PA, PU, H, Q, %, MC, MCr, MM, MS, ME, MCu, MAl, ML, M)"
 
-#: ../Generic/fiebdc.py:150
-msgid "Invalid code, it must be a unicode string"
-msgstr "Código no válido, debe ser una cadena unicode"
+#: ../Generic/fiebdc.py:156
+msgid "Invalid code, it must be a text string"
+msgstr "Código no válido, debe ser una cadena de texto"
 
-#: ../Generic/fiebdc.py:157
+#: ../Generic/fiebdc.py:164
 msgid "The code '$1' have invalid characters, replaced by '$2'."
 msgstr "El código «$1» tiene caracteres inválidos, reemplazado por «$2»."
 
-#: ../Generic/fiebdc.py:160
-msgid "The code '$1' have invalid characters and can not be encoded in utf8."
+#: ../Generic/fiebdc.py:169
+msgid "The code '$1' have invalid characters and can not be encoded in utf-8."
 msgstr ""
 "El código «$1» tiene caracteres inválidos y no puede ser codificado en utf8."
 
-#: ../Generic/fiebdc.py:187
+#: ../Generic/fiebdc.py:206
 msgid "The code '$1' contains special characters repeated."
 msgstr "El código «$1» contiene caractectes especiales repetidos."
 
-#: ../Generic/fiebdc.py:391
+#: ../Generic/fiebdc.py:411
 msgid "FIEBDC. Unknow record: $1"
 msgstr "FIEBDC. Registro desconocido: $1"
 
-#: ../Generic/fiebdc.py:410
+#: ../Generic/fiebdc.py:432
 msgid ""
 "The 'V' record (Property and Version) must be the first record in the file "
 "but it is the number: $1"
@@ -616,27 +611,27 @@
 "El registro «V» (Propiedad y  versión) debe ser el primer registro en el "
 "archivo pero es el número: $1"
 
-#: ../Generic/fiebdc.py:413
+#: ../Generic/fiebdc.py:437
 msgid "The default values were taken and this V record is ignored"
 msgstr "El valor por amisión ha sido tomado y el registro V es ignorado"
 
-#: ../Generic/fiebdc.py:447
+#: ../Generic/fiebdc.py:472
 msgid "FIEBDC format: $1"
 msgstr "FIEBDC formato: $1"
 
-#: ../Generic/fiebdc.py:457
+#: ../Generic/fiebdc.py:484
 msgid "FIEBDC file generated by $1"
 msgstr "FIEBDC fichero generado por $1"
 
-#: ../Generic/fiebdc.py:798
+#: ../Generic/fiebdc.py:825
 msgid "Record C without a valid code"
 msgstr "Registro C sin un código válido"
 
-#: ../Generic/fiebdc.py:876 ../Generic/fiebdc.py:888 ../Generic/fiebdc.py:916
+#: ../Generic/fiebdc.py:904 ../Generic/fiebdc.py:917 ../Generic/fiebdc.py:946
 msgid "Incorrect type ($1) in the code $2"
 msgstr "Tipo incorrecto ($1) en el código $2"
 
-#: ../Generic/fiebdc.py:970
+#: ../Generic/fiebdc.py:1001
 msgid ""
 "ValueError loadig the descomposition of the record $1, the factor of the "
 "child $2 must be a float number and can not be $3, seted default value 1.0"
@@ -645,7 +640,7 @@
 "hijo $2 debe ser un número de coma flotante y no puede ser $3, fijado el "
 "valor por omisión 1.0"
 
-#: ../Generic/fiebdc.py:981
+#: ../Generic/fiebdc.py:1013
 msgid ""
 "ValueError loading the descomposition of the record $1, the yield of the "
 "child $2, must be a float number and cannot be $3,  seted default value 1.0"
@@ -654,25 +649,25 @@
 "del hijo $2, debe ser un número de coma flotante y no puede ser $3, fijado "
 "el valor por omisión 1.0"
 
-#: ../Generic/fiebdc.py:1070
+#: ../Generic/fiebdc.py:1102
 msgid "Invalid codes in $1 record, codes $2"
 msgstr "Códigos no válidos en registro $1, códigos $2"
 
-#: ../Generic/fiebdc.py:1074
+#: ../Generic/fiebdc.py:1107
 msgid "Empty child code in $1 record, codes: $2"
 msgstr "Código de hijo vacío en el registro $1, códigos: $2"
 
-#: ../Generic/fiebdc.py:1094
+#: ../Generic/fiebdc.py:1128
 msgid "Invalid path in $1 record, codes $2"
 msgstr "Camino no válido en el registro $1, códigos $2"
 
-#: ../Generic/fiebdc.py:1105
+#: ../Generic/fiebdc.py:1140
 msgid "Invalid Total Measure value in $1 record, codes $2. Total fixed to 0."
 msgstr ""
 "El Total de la medición no es válido en el registro $1, códigos $2. Total "
 "fijado a 0."
 
-#: ../Generic/fiebdc.py:1126
+#: ../Generic/fiebdc.py:1162
 msgid ""
 "The comment is not a formula or its have invalid characters, in the $1 "
 "record, codes $2"
@@ -680,294 +675,330 @@
 "El comentario no es una fórmula o tiene caracteres inválidos, en el registro "
 "$1, códigos $2"
 
-#: ../Generic/fiebdc.py:1152
+#: ../Generic/fiebdc.py:1189
 msgid "The measure values are not float numbers, code $1"
 msgstr "«Measure» debe ser un número de coma flotante. Tipo: $1"
 
-#: ../Generic/fiebdc.py:1452 ../Generic/fiebdc.py:1717
+#: ../Generic/fiebdc.py:1493 ../Generic/fiebdc.py:1761
 msgid "The file $1 do not exist"
 msgstr "El archivo $1 no existe"
 
-#: ../Generic/fiebdc.py:1823 ../Generic/fiebdc.py:1830
+#: ../Generic/fiebdc.py:1869 ../Generic/fiebdc.py:1877
 msgid "PyArq hates parametric DLLs"
 msgstr "PyArq odia las DLLs paramétricas"
 
-#: ../Generic/fiebdc.py:2028
+#: ../Generic/fiebdc.py:1985
+msgid "Parametric: code:  $1"
+msgstr "Registro parametrico: código:  $1"
+
+#: ../Generic/fiebdc.py:1988
+msgid "******* Desconocido *** : $1"
+msgstr "******* Desconocido *** : $1"
+
+#: ../Generic/fiebdc.py:2103
 msgid "Loading file $1"
 msgstr "Cargando archivo $1"
 
-#: ../Generic/fiebdc.py:2049
+#: ../Generic/fiebdc.py:2125
 msgid "FIEBDC character encoding: $1"
 msgstr "FIEBDC codificación de caracteres: $1"
 
-#: ../Generic/fiebdc.py:2053
+#: ../Generic/fiebdc.py:2129
 msgid ""
 "This Character encoding do not exist in FIEBDC3! Default Character encoding: "
 "$1"
 msgstr "¡Esta codificación no existe en FIEBDC3! Codificación por omisión: $1"
 
-#: ../Generic/fiebdc.py:2058
+#: ../Generic/fiebdc.py:2134
 msgid ""
 "This V record dot have a character encoding! Default character encoding: $1"
 msgstr "¡Este registro V no define codificación! Codificación por omisión: $1"
 
-#: ../Generic/fiebdc.py:2063
+#: ../Generic/fiebdc.py:2139
 msgid "Not 'V' record in File! Default character encoding: $1"
 msgstr "¡No hay registro «V» en el archivo! Codificación por omisión: $1"
 
-#: ../Generic/fiebdc.py:2111
+#: ../Generic/fiebdc.py:2187
 msgid "$1 unsuported record type O: Comercial Relationship"
 msgstr "$1 tipo de registro no soportado O: Releción comercial"
 
-#: ../Generic/fiebdc.py:2114
+#: ../Generic/fiebdc.py:2191
 msgid "This file is not a valid FIBDC3 file"
 msgstr "El archivo no es un archivo FIEBDC3 válido"
 
-#: ../Generic/fiebdc.py:2127
+#: ../Generic/fiebdc.py:2205
 msgid "Testing budget ..."
 msgstr "Comprobando presupuesto ..."
 
-#: ../Generic/fiebdc.py:2146
+#: ../Generic/fiebdc.py:2225
 msgid "End Test"
 msgstr "Comprobación finalizada"
 
-#: ../Generic/fiebdc.py:2230 ../Gtk/gui.py:1038
+#: ../Generic/fiebdc.py:2312 ../Gtk/gui.py:1074
 msgid "Process terminated"
 msgstr "Proceso cancelado"
 
-#: ../Generic/fiebdc.py:2312
+#: ../Generic/fiebdc.py:2396
 msgid "Time to load: $1 seconds"
 msgstr "Tiempo de carga: $1 segundos"
 
-#: ../Generic/fiebdc.py:2314
+#: ../Generic/fiebdc.py:2398
 msgid "Records/Valid Records: $1/$2"
 msgstr "Registro/Registros válidos: $1/$2"
 
-#: ../Gtk/gui.py:83 ../Gtk/gui.py:89
+#: ../Generic/utils.py:154
+msgid "Not a text string, code: $1, type: $2"
+msgstr "No es una cadena de texto, código: $1, tipo: $2"
+
+#: ../Generic/utils.py:168
+msgid "Unicode Error, code: $1"
+msgstr "Unicode Error, código: $1"
+
+#: ../Generic/utils.py:173
+msgid "Not in cp850, code: $1"
+msgstr "No en cp850, código: $1"
+
+#: ../Generic/utils.py:182
+msgid "Control characters in code: $1"
+msgstr "Carácteres de control en el código: $1"
+
+#: ../Generic/utils.py:190
+msgid "# in code: $1"
+msgstr "# en Código: $1"
+
+#: ../Generic/utils.py:197
+msgid "Empty code"
+msgstr "Código vacio"
+
+#: ../Gtk/gui.py:103 ../Gtk/gui.py:110
 msgid "The icon file does not exist. '$1'"
 msgstr "El archivo de icono no existe. «$1»"
 
-#: ../Gtk/gui.py:95
+#: ../Gtk/gui.py:117
 msgid "pyArq-Presupuestos running on $1"
 msgstr "pyArq-Presupuestos ejecutandose en $1"
 
-#: ../Gtk/gui.py:176
+#: ../Gtk/gui.py:200
 msgid "_New window"
 msgstr "Ventana _Nueva"
 
-#: ../Gtk/gui.py:177
+#: ../Gtk/gui.py:201
 msgid "_Close window"
 msgstr "_Cerrar ventana"
 
-#: ../Gtk/gui.py:182
+#: ../Gtk/gui.py:206
 msgid "About"
 msgstr "Acerca de"
 
-#: ../Gtk/gui.py:185
+#: ../Gtk/gui.py:209
 msgid "_Quit application"
 msgstr "_Cerrar aplicación"
 
-#: ../Gtk/gui.py:195
+#: ../Gtk/gui.py:219
 msgid "_Import Fiebdc"
 msgstr "_Importar Fiebdc"
 
-#: ../Gtk/gui.py:199 ../Gtk/gui.py:400 ../Gtk/gui.py:955
+#: ../Gtk/gui.py:224 ../Gtk/gui.py:426 ../Gtk/gui.py:990
 msgid "_Close tab"
 msgstr "_Cerrar pestaña"
 
-#: ../Gtk/gui.py:203
+#: ../Gtk/gui.py:228
 msgid "_File"
 msgstr "_Archivo"
 
-#: ../Gtk/gui.py:205
+#: ../Gtk/gui.py:230
 msgid "_Back"
 msgstr "A_tras"
 
-#: ../Gtk/gui.py:208
+#: ../Gtk/gui.py:233
 msgid "_Forward"
 msgstr "A_delante"
 
-#: ../Gtk/gui.py:211
+#: ../Gtk/gui.py:236
 msgid "_Up Item"
 msgstr "Concepto _Superior"
 
-#: ../Gtk/gui.py:214
+#: ../Gtk/gui.py:239
 msgid "_Root"
 msgstr "_Raiz"
 
-#: ../Gtk/gui.py:217
+#: ../Gtk/gui.py:242
 msgid "_Go"
 msgstr "_Ir"
 
-#: ../Gtk/gui.py:391 ../Gtk/gui.py:392
+#: ../Gtk/gui.py:417 ../Gtk/gui.py:418
 msgid "Import Fiebdc"
 msgstr "Importar Fiebdc"
 
-#: ../Gtk/gui.py:401 ../Gtk/gui.py:956
+#: ../Gtk/gui.py:427 ../Gtk/gui.py:991
 msgid "Close tab"
 msgstr "Cerrar pestaña"
 
-#: ../Gtk/gui.py:413 ../Gtk/gui.py:414
+#: ../Gtk/gui.py:439 ../Gtk/gui.py:440
 msgid "Back"
 msgstr "Atras"
 
-#: ../Gtk/gui.py:422 ../Gtk/gui.py:423
+#: ../Gtk/gui.py:449 ../Gtk/gui.py:450
 msgid "Forward"
 msgstr "Adelante"
 
-#: ../Gtk/gui.py:431 ../Gtk/gui.py:432
+#: ../Gtk/gui.py:458 ../Gtk/gui.py:459
 msgid "Up Item"
 msgstr "Concepto Superior"
 
-#: ../Gtk/gui.py:440 ../Gtk/gui.py:441
+#: ../Gtk/gui.py:467 ../Gtk/gui.py:468
 msgid "Root"
 msgstr "Raiz"
 
-#: ../Gtk/gui.py:655
+#: ../Gtk/gui.py:684
 msgid "The page is not in the page list"
 msgstr "La pestaña no está en la lista de pestañas"
 
-#: ../Gtk/gui.py:792 ../Gtk/gui.py:793
+#: ../Gtk/gui.py:823 ../Gtk/gui.py:824
 msgid "Open File"
 msgstr "Abrir archivo"
 
-#: ../Gtk/gui.py:794
+#: ../Gtk/gui.py:825
 msgid "Cancel"
 msgstr "Cancelar"
 
-#: ../Gtk/gui.py:833
+#: ../Gtk/gui.py:868
 msgid "The file must have 'bc3' extension"
 msgstr "El archivo debe tener extensión «bc3»"
 
-#: ../Gtk/gui.py:991
+#: ../Gtk/gui.py:1027
 msgid "Time: 0s"
 msgstr "Tiempo: 0s"
 
-#: ../Gtk/gui.py:1104
+#: ../Gtk/gui.py:1140
 msgid "Time: $1"
 msgstr "Tiempo: $1"
 
-#: ../Gtk/gui.py:1455
+#: ../Gtk/gui.py:1492
 msgid "The value must be a list"
 msgstr "El valor debe ser una lista"
 
-#: ../Gtk/gui.py:1458
+#: ../Gtk/gui.py:1497
 msgid "Incorrect len"
 msgstr "Longuitud incorrecta"
 
-#: ../Gtk/gui.py:1486
+#: ../Gtk/gui.py:1528
 msgid "Incorrect item $1"
 msgstr "Elemento incorrecto $1"
 
-#: ../Gtk/gui.py:1502
+#: ../Gtk/gui.py:1546
 msgid "The budget does not have the path record: $1"
 msgstr "El presupuesto no tiene el registro con camino: $1"
 
-#: ../Gtk/gui.py:1865
+#: ../Gtk/gui.py:1911
 msgid "Decomposition"
 msgstr "Descomposición"
 
-#: ../Gtk/gui.py:1866 ../Gtk/gui.py:2895
+#: ../Gtk/gui.py:1912 ../Gtk/gui.py:2956
 msgid "Description"
 msgstr "Descripción"
 
-#: ../Gtk/gui.py:1867 ../Gtk/gui.py:2897
+#: ../Gtk/gui.py:1913 ../Gtk/gui.py:2960
 msgid "Measure"
 msgstr "Medición"
 
-#: ../Gtk/gui.py:1868
+#: ../Gtk/gui.py:1914
 msgid "Sheet of Conditions"
 msgstr "Pliego de condicones"
 
-#: ../Gtk/gui.py:1869
+#: ../Gtk/gui.py:1915
 msgid "Files"
 msgstr "Archivos"
 
-#: ../Gtk/gui.py:1870
+#: ../Gtk/gui.py:1916
 msgid "Companies"
 msgstr "Entidades"
 
-#: ../Gtk/gui.py:1950
+#: ../Gtk/gui.py:1964
+msgid "Invalid type of View: $1"
+msgstr "Tipo invalido de vista: $1"
+
+#: ../Gtk/gui.py:1998
 msgid "Split View Left/Right"
 msgstr "Partir vista Izquierda/Derecha"
 
-#: ../Gtk/gui.py:1960
+#: ../Gtk/gui.py:2008
 msgid "Split View Top/Bottom"
 msgstr "Partir vista Arriba/Abajo"
 
-#: ../Gtk/gui.py:1968
+#: ../Gtk/gui.py:2017
 msgid "Disconnect view"
 msgstr "Desconectar vista"
 
-#: ../Gtk/gui.py:1971
+#: ../Gtk/gui.py:2021
 msgid "Connect view"
 msgstr "Concectar vista"
 
-#: ../Gtk/gui.py:1984 ../Gtk/gui.py:2081
+#: ../Gtk/gui.py:2034 ../Gtk/gui.py:2131
 msgid "Close view"
 msgstr "Cerrar vista"
 
-#: ../Gtk/gui.py:2073
+#: ../Gtk/gui.py:2123
 msgid "Split view Left/Right"
 msgstr "Partir vista Izquierda/Derecha"
 
-#: ../Gtk/gui.py:2077
+#: ../Gtk/gui.py:2127
 msgid "Split view Top/Bottom"
 msgstr "Partir vista Arriba/Abajo"
 
-#: ../Gtk/gui.py:2112
+#: ../Gtk/gui.py:2163
 msgid "Connect View"
 msgstr "Conectar vista"
 
-#: ../Gtk/gui.py:2118
+#: ../Gtk/gui.py:2169
 msgid "Disconnect View"
 msgstr "Desconectar vista"
 
-#: ../Gtk/gui.py:2248
+#: ../Gtk/gui.py:2299
 msgid "The item must be a widget object."
 msgstr "El elemento debe ser un objeto «widget»."
 
-#: ../Gtk/gui.py:2256
+#: ../Gtk/gui.py:2309
 msgid "Invalid orientation."
 msgstr "Orientación no válida"
 
-#: ../Gtk/gui.py:2628 ../Gtk/gui.py:3256 ../Gtk/gui.py:4674
+#: ../Gtk/gui.py:2683 ../Gtk/gui.py:3321 ../Gtk/gui.py:4756
 msgid "Argument must be a Budget object"
 msgstr "El argumento debe ser un objeto «Budget»"
 
-#: ../Gtk/gui.py:2892 ../Gtk/gui.py:4739
+#: ../Gtk/gui.py:2952 ../Gtk/gui.py:4823
 msgid "Code"
 msgstr "Código"
 
-#: ../Gtk/gui.py:2893
+#: ../Gtk/gui.py:2954
 msgid "Unit"
 msgstr "Unidad"
 
-#: ../Gtk/gui.py:2899
+#: ../Gtk/gui.py:2962
 msgid "Price"
 msgstr "Precio"
 
-#: ../Gtk/gui.py:2901
+#: ../Gtk/gui.py:2964
 msgid "Amount"
 msgstr "Importe"
 
-#: ../Gtk/gui.py:2912 ../Gtk/gui.py:3528
+#: ../Gtk/gui.py:2975 ../Gtk/gui.py:3598
 msgid "Invalid path"
 msgstr "Ruta no válida"
 
-#: ../Gtk/gui.py:3261
+#: ../Gtk/gui.py:3328
 msgid "Record path must be a tuple"
 msgstr "La posición del registro debe ser una tupla"
 
-#: ../Gtk/gui.py:3509 ../Gtk/gui.py:4754 ../Gtk/gui.py:5066
+#: ../Gtk/gui.py:3579 ../Gtk/gui.py:4838 ../Gtk/gui.py:5154
 msgid "Type"
 msgstr "Tipo"
 
-#: ../Gtk/gui.py:3510
+#: ../Gtk/gui.py:3580
 msgid "Comment"
 msgstr "Comentario"
 
-#: ../Gtk/gui.py:3511
+#: ../Gtk/gui.py:3581
 msgid ""
 "N\n"
 "(a)"
@@ -975,7 +1006,7 @@
 "N\n"
 "(a)"
 
-#: ../Gtk/gui.py:3512
+#: ../Gtk/gui.py:3582
 msgid ""
 "Length\n"
 "(b)"
@@ -983,7 +1014,7 @@
 "Longitud\n"
 "(b)"
 
-#: ../Gtk/gui.py:3513
+#: ../Gtk/gui.py:3583
 msgid ""
 "Width\n"
 "(c)"
@@ -991,7 +1022,7 @@
 "Anchura\n"
 "(c)"
 
-#: ../Gtk/gui.py:3514
+#: ../Gtk/gui.py:3584
 msgid ""
 "Height\n"
 "(d)"
@@ -999,11 +1030,11 @@
 "Altura\n"
 "(d)"
 
-#: ../Gtk/gui.py:3515
+#: ../Gtk/gui.py:3585
 msgid "Formula"
 msgstr "Fórmula"
 
-#: ../Gtk/gui.py:3516
+#: ../Gtk/gui.py:3586
 #, python-format
 msgid ""
 "Parcial\n"
@@ -1012,79 +1043,79 @@
 "Parcial\n"
 "[%s]"
 
-#: ../Gtk/gui.py:3517
+#: ../Gtk/gui.py:3587
 msgid "Subtotal"
 msgstr "Subtotal"
 
-#: ../Gtk/gui.py:3537
+#: ../Gtk/gui.py:3609
 msgid "measure must be a Measure object. Type: $1"
 msgstr "«measure» debe ser un objeto «Measure». Tipo: $1"
 
-#: ../Gtk/gui.py:3835 ../Gtk/gui.py:3856
+#: ../Gtk/gui.py:3909 ../Gtk/gui.py:3931
 msgid "Description text of the record $1"
 msgstr "Texto descriptivo del registro $1"
 
-#: ../Gtk/gui.py:4010
+#: ../Gtk/gui.py:4086
 msgid "Sheet of Conditions of the record $1"
 msgstr "Pliego de condiciones del registro $1"
 
-#: ../Gtk/gui.py:4031
+#: ../Gtk/gui.py:4108
 msgid "Field"
 msgstr "Ámbito"
 
-#: ../Gtk/gui.py:4054
+#: ../Gtk/gui.py:4132
 msgid "Section"
 msgstr "Sección"
 
-#: ../Gtk/gui.py:4214
+#: ../Gtk/gui.py:4295
 msgid "Sheet2 of Conditions of the record $1"
 msgstr "Pliego2 de condiciones del registro $1"
 
-#: ../Gtk/gui.py:4740
+#: ../Gtk/gui.py:4824
 msgid "Code that define the company"
 msgstr "Código que define la entidad"
 
-#: ../Gtk/gui.py:4741
+#: ../Gtk/gui.py:4825
 msgid "Summary"
 msgstr "Resumen"
 
-#: ../Gtk/gui.py:4742
+#: ../Gtk/gui.py:4826
 msgid "Summary of the company name"
 msgstr "Resumen del nombre de la entidad"
 
-#: ../Gtk/gui.py:4743 ../Gtk/gui.py:4759
+#: ../Gtk/gui.py:4827 ../Gtk/gui.py:4843
 msgid "Name"
 msgstr "Nombre"
 
-#: ../Gtk/gui.py:4744
+#: ../Gtk/gui.py:4828
 msgid "Complete name"
 msgstr "Nombre completo"
 
-#: ../Gtk/gui.py:4745
+#: ../Gtk/gui.py:4829
 msgid "CIF"
 msgstr "CIF"
 
-#: ../Gtk/gui.py:4746
+#: ../Gtk/gui.py:4830
 msgid "Fiscal identifier number"
 msgstr "Número de identificación fiscal"
 
-#: ../Gtk/gui.py:4747
+#: ../Gtk/gui.py:4831
 msgid "Web"
 msgstr "Web"
 
-#: ../Gtk/gui.py:4748
+#: ../Gtk/gui.py:4832
 msgid "Company web page"
 msgstr "Página web de la entidad"
 
-#: ../Gtk/gui.py:4749
+#: ../Gtk/gui.py:4833
 msgid "Email"
 msgstr "Email"
 
-#: ../Gtk/gui.py:4750
+#: ../Gtk/gui.py:4834
 msgid "Company email"
 msgstr "Correo electrónico de la entidad"
 
-#: ../Gtk/gui.py:4755
+#: ../Gtk/gui.py:4839
 msgid ""
 "Type of Office:\n"
 "                           C: Central office\n"
@@ -1096,134 +1127,143 @@
 "                           D: Delegación\n"
 "                           R: Representante"
 
-#: ../Gtk/gui.py:4760
+#: ../Gtk/gui.py:4844
 msgid "Office name"
 msgstr "Nombre de la oficina"
 
-#: ../Gtk/gui.py:4761
+#: ../Gtk/gui.py:4845
 msgid "Address"
 msgstr "Dirección"
 
-#: ../Gtk/gui.py:4762
+#: ../Gtk/gui.py:4846
 msgid "Postal code"
 msgstr "Código postal"
 
-#: ../Gtk/gui.py:4763
+#: ../Gtk/gui.py:4847
 msgid "Town"
 msgstr "Ciudad"
 
-#: ../Gtk/gui.py:4764
+#: ../Gtk/gui.py:4848
 msgid "Province"
 msgstr "Provincia"
 
-#: ../Gtk/gui.py:4765
+#: ../Gtk/gui.py:4849
 msgid "Country"
 msgstr "Ciudad"
 
-#: ../Gtk/gui.py:4766
+#: ../Gtk/gui.py:4850
 msgid "Phone"
 msgstr "Teléfono"
 
-#: ../Gtk/gui.py:4767
+#: ../Gtk/gui.py:4851
 msgid "Phone numbers of the office"
 msgstr "Teléfono de la officina"
 
-#: ../Gtk/gui.py:4768
+#: ../Gtk/gui.py:4852
 msgid "Fax"
 msgstr "Fax"
 
-#: ../Gtk/gui.py:4769
+#: ../Gtk/gui.py:4853
 msgid "Fax numbers of the office"
 msgstr "Fax de la oficina"
 
-#: ../Gtk/gui.py:4770
+#: ../Gtk/gui.py:4854
 msgid "Contact person"
 msgstr "Persona de contacto"
 
-#: ../Gtk/gui.py:4771
+#: ../Gtk/gui.py:4855
 msgid "Contact persons in the office"
 msgstr "Persona de contacto en la oficina"
 
-#: ../Gtk/gui.py:4775
+#: ../Gtk/gui.py:4859
 msgid "Unknow Option Type"
 msgstr "Tipo de opcion desconocida"
 
-#: ../Gtk/gui.py:5002
+#: ../Gtk/gui.py:5090
 msgid "Boolean"
 msgstr "Booleano"
 
-#: ../Gtk/gui.py:5003
+#: ../Gtk/gui.py:5091
 msgid "Integer"
 msgstr "Entero"
 
-#: ../Gtk/gui.py:5004
+#: ../Gtk/gui.py:5092
 msgid "Text"
 msgstr "Texto"
 
-#: ../Gtk/gui.py:5005
+#: ../Gtk/gui.py:5093
 msgid "Color"
 msgstr "Color"
 
-#: ../Gtk/gui.py:5006
+#: ../Gtk/gui.py:5094
 msgid "List"
 msgstr "Lista"
 
-#: ../Gtk/gui.py:5040
+#: ../Gtk/gui.py:5128
 msgid "Option name"
 msgstr "Nombre de Opción"
 
-#: ../Gtk/gui.py:5053
+#: ../Gtk/gui.py:5141
 msgid "Value"
 msgstr "Valor"
 
-#: ../Gtk/gui.py:5094
+#: ../Gtk/gui.py:5182
 msgid "Description:"
 msgstr "Descripción:"
 
-#: ../Gtk/gui.py:5258
+#: ../Gtk/gui.py:5343
 msgid "Option values must be strings"
 msgstr "Los valores de la opción deben ser cadenas"
 
-#: ../Gtk/gui.py:5260
+#: ../Gtk/gui.py:5345
 msgid "Option must be a tuple with 4 items"
 msgstr "La opcion debe ser una tupla de 4 elementos"
 
-#: ../Gtk/gui.py:5262
+#: ../Gtk/gui.py:5347
 msgid "Option list must be a list"
 msgstr "La lista de opciones debe ser una lista lista"
 
-#: ../Gtk/gui.py:5282
+#: ../Gtk/gui.py:5367
 msgid "Icorrect type, must be boolean"
 msgstr "Tipo erroneo, debe ser booleano"
 
-#: ../Gtk/gui.py:5287
+#: ../Gtk/gui.py:5372
 msgid "Icorrect type, must be integer"
 msgstr "Tipo erroneo, debe ser un número entero"
 
-#: ../Gtk/gui.py:5300
+#: ../Gtk/gui.py:5385
 msgid "Icorrect type, must be string"
 msgstr "Tipo erroneo, debe ser una cadena de texto"
 
-#: ../Gtk/gui.py:5313
+#: ../Gtk/gui.py:5398
 msgid "Icorrect type, must be list"
 msgstr "Tipo erroneo, debe ser una lista"
 
-#: ../Gtk/gui.py:5317
+#: ../Gtk/gui.py:5402
 msgid "Icorrect type, must be a parseable color"
 msgstr "Tipo erroneo, debe ser un color parseable"
 
-#: ../Gtk/gui.py:5325
+#: ../Gtk/gui.py:5410
 msgid "Type must be boolean, integer, string or color"
 msgstr "El tipo debe ser booleano, entero, cadena de texto o color"
 
-#: ../Gtk/gui.py:5328
+#: ../Gtk/gui.py:5413
 msgid "Value must be in the option dict"
 msgstr "El valor debe estar en el diccionario de opciones"
 
-#: ../Gtk/gui.py:5331
+#: ../Gtk/gui.py:5416
 msgid "Values must be a dict"
 msgstr "El valor debe ser un dicionario"
 
+#~ msgid "Price must be a float number: $1"
+#~ msgstr "Precio debe ser un número de coma flotante: $1"
+
+#~ msgid "Measure Comment must be a string ($1)"
+#~ msgstr "El comentario de la medición debe ser una cadena ($1)"
+
+#~ msgid "The summary must be a string"
+#~ msgstr "El resumen debe ser una cadena de texto"
+
 #~ msgid "Incorrent Base version"
 #~ msgstr "Versión de la Base incorrecta"
 
--- a/mo/pyArq-Presupuestos.pot	Mon May 20 13:18:33 2019 +0200
+++ b/mo/pyArq-Presupuestos.pot	Tue Jun 18 17:50:23 2019 +0200
@@ -8,7 +8,7 @@
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-04-27 10:53+0200\n"
+"POT-Creation-Date: 2019-06-18 11:57+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,14 +17,14 @@
 "Content-Type: text/plain; charset=CHARSET\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: ../Generic/base.py:283
+#: ../Generic/base.py:285
 msgid ""
 "\n"
 "A free program of measurements, budgets and control of construction sites.\n"
 "In beta development, still there is not a fully functional version.\n"
 msgstr ""
 
-#: ../Generic/base.py:288
+#: ../Generic/base.py:290
 msgid ""
 "\n"
 "Usage:\n"
@@ -34,993 +34,1024 @@
 "    -h, --help     Show this help\n"
 msgstr ""
 
-#: ../Generic/base.py:421
+#: ../Generic/base.py:423
 msgid "Invalid code: $1"
 msgstr ""
 
-#: ../Generic/base.py:436
+#: ../Generic/base.py:440
 msgid "Synonyms ($1) must be a list, code: $2"
 msgstr ""
 
-#: ../Generic/base.py:440
+#: ../Generic/base.py:446
 msgid "Invalid Code in synomyms list ($1) code: $2"
 msgstr ""
 
-#: ../Generic/base.py:471
-msgid "Unit ($1) must be a string: $2"
+#: ../Generic/base.py:479
+msgid "Unit ($1) must be a text string: $2"
 msgstr ""
 
-#: ../Generic/base.py:485
-msgid "Summary ($1) must be a string: $1"
+#: ../Generic/base.py:495
+msgid "Summary ($1) must be a text string: $1"
 msgstr ""
 
-#: ../Generic/base.py:502
+#: ../Generic/base.py:514
 msgid "Prices ($1) must be a list: $2"
 msgstr ""
 
-#: ../Generic/base.py:523
+#: ../Generic/base.py:537
 msgid "Price ($1) must be a list with two items: $2"
 msgstr ""
 
-#: ../Generic/base.py:528
-msgid "Price must be a float number: $1"
+#: ../Generic/base.py:556
+msgid "The record do not have this Price. Code: $1"
 msgstr ""
 
-#: ../Generic/base.py:538
-#, python-format
-msgid "The record do not have this Price. Code: %s"
-msgstr ""
-
-#: ../Generic/base.py:544
+#: ../Generic/base.py:564
 msgid "The record do not have this Price"
 msgstr ""
 
-#: ../Generic/base.py:559
+#: ../Generic/base.py:581
 msgid "Parents ($1) must be a list: $2"
 msgstr ""
 
-#: ../Generic/base.py:563 ../Generic/base.py:575
+#: ../Generic/base.py:587 ../Generic/base.py:601
 msgid "Invalid parent code ($1) in the record: $2"
 msgstr ""
 
-#: ../Generic/base.py:591
+#: ../Generic/base.py:619
 msgid "children ($1) must be a list, record: $2"
 msgstr ""
 
-#: ../Generic/base.py:595
+#: ../Generic/base.py:625
 msgid "child ($1) must be a Decomposition object, record: $2"
 msgstr ""
 
-#: ../Generic/base.py:649
-msgid "Text ($1) must be a string, record: $2"
+#: ../Generic/base.py:680
+msgid "Text ($1) must be a text string, record: $2"
 msgstr ""
 
-#: ../Generic/base.py:662
+#: ../Generic/base.py:695
 msgid "sheet must be a Sheet instance"
 msgstr ""
 
-#: ../Generic/base.py:674
+#: ../Generic/base.py:709
 msgid "files must be a list: $1"
 msgstr ""
 
-#: ../Generic/base.py:685 ../Generic/base.py:699
+#: ../Generic/base.py:722 ../Generic/base.py:740
 msgid "Incorrect path"
 msgstr ""
 
-#: ../Generic/base.py:690
+#: ../Generic/base.py:728
 msgid "file must be a list or a File object: $1"
 msgstr ""
 
-#: ../Generic/base.py:718
+#: ../Generic/base.py:761
 msgid "labels must be a list"
 msgstr ""
 
-#: ../Generic/base.py:724
-msgid "label must be a string"
+#: ../Generic/base.py:769
+msgid "label must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:733
-msgid "Label must be a string"
+#: ../Generic/base.py:780
+msgid "Label must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:981
+#: ../Generic/base.py:1030
 msgid "Position must be a integer"
 msgstr ""
 
-#: ../Generic/base.py:995
+#: ../Generic/base.py:1046
 msgid "BudgetMeasures atribute must be a list"
 msgstr ""
 
-#: ../Generic/base.py:998
-msgid "BudgetMeasures item must be a Measure "
+#: ../Generic/base.py:1051
+msgid "BudgetMeasures item must be a Measure object"
 msgstr ""
 
-#: ../Generic/base.py:1007
+#: ../Generic/base.py:1061
 msgid "Certification atribute must be a list or None"
 msgstr ""
 
-#: ../Generic/base.py:1015
+#: ../Generic/base.py:1071
 msgid "Real cost atribute must be a list or None"
 msgstr ""
 
-#: ../Generic/base.py:1023
+#: ../Generic/base.py:1081
 msgid "Cost goals atribute must be a list or None"
 msgstr ""
 
-#: ../Generic/base.py:1031
+#: ../Generic/base.py:1091
 msgid "Cost Planned atribute must be a list or None"
 msgstr ""
 
-#: ../Generic/base.py:1124
+#: ../Generic/base.py:1186
 msgid "Measure must be a float number. Type: $1"
 msgstr ""
 
-#: ../Generic/base.py:1136
+#: ../Generic/base.py:1200
 msgid "Lines must be a list"
 msgstr ""
 
-#: ../Generic/base.py:1139
+#: ../Generic/base.py:1205
 msgid "Line must be a MeasureLine objetc"
 msgstr ""
 
-#: ../Generic/base.py:1150
+#: ../Generic/base.py:1218
 msgid "Factor must be a float number |$1|"
 msgstr ""
 
-#: ../Generic/base.py:1162
+#: ../Generic/base.py:1232
 msgid "Yield must be a float number"
 msgstr ""
 
-#: ../Generic/base.py:1173
+#: ../Generic/base.py:1245
 msgid "Fixed must be boolean object"
 msgstr ""
 
-#: ../Generic/base.py:1243
+#: ../Generic/base.py:1317
 msgid "Type must be M or A. Type: $1"
 msgstr ""
 
-#: ../Generic/base.py:1387
-msgid " Parcial Subtotal must be a float number. Parcial: $1"
+#: ../Generic/base.py:1463
+msgid "Parcial Subtotal must be a float number. Parcial: $1"
 msgstr ""
 
-#: ../Generic/base.py:1395
-msgid " Acumulated Subtotal must be a float number. Parcial: $1"
+#: ../Generic/base.py:1473
+msgid "Acumulated Subtotal must be a float number. Parcial: $1"
 msgstr ""
 
-#: ../Generic/base.py:1431
+#: ../Generic/base.py:1510
 msgid "Invalid measure line type ($1)"
 msgstr ""
 
-#: ../Generic/base.py:1437
-msgid "Measure Comment must be a string ($1)"
-msgstr ""
-
-#: ../Generic/base.py:1444
+#: ../Generic/base.py:1527
 msgid "Invalid Measure Units ($1)"
 msgstr ""
 
-#: ../Generic/base.py:1457
+#: ../Generic/base.py:1542
 msgid "Invalid Measure length ($1)"
 msgstr ""
 
-#: ../Generic/base.py:1470
+#: ../Generic/base.py:1557
 msgid "Invalid Measure Width ($1)"
 msgstr ""
 
-#: ../Generic/base.py:1483
+#: ../Generic/base.py:1572
 msgid "Invalid Measure Height ($1)"
 msgstr ""
 
-#: ../Generic/base.py:1495
-msgid "Formula must be a string ($1)"
+#: ../Generic/base.py:1586
+msgid "Formula must be a text string ($1)"
 msgstr ""
 
-#: ../Generic/base.py:1498
-msgid "There is invalid charactersin formula ($1)"
+#: ../Generic/base.py:1591
+msgid "There is invalid characters in formula ($1)"
 msgstr ""
 
-#: ../Generic/base.py:1564 ../Generic/base.py:2618
+#: ../Generic/base.py:1659 ../Generic/base.py:2776
 msgid "'a' value must be a float number"
 msgstr ""
 
-#: ../Generic/base.py:1568 ../Generic/base.py:2622
+#: ../Generic/base.py:1665 ../Generic/base.py:2782
 msgid "'b' value must be a float number"
 msgstr ""
 
-#: ../Generic/base.py:1572 ../Generic/base.py:2626
+#: ../Generic/base.py:1671 ../Generic/base.py:2788
 msgid "'c' value must be a float number"
 msgstr ""
 
-#: ../Generic/base.py:1576 ../Generic/base.py:2630
+#: ../Generic/base.py:1677 ../Generic/base.py:2794
 msgid "'d' value must be a float number"
 msgstr ""
 
-#: ../Generic/base.py:1604 ../Generic/base.py:2658
+#: ../Generic/base.py:1707 ../Generic/base.py:2824
 msgid "Invalid formula"
 msgstr ""
 
-#: ../Generic/base.py:1858
+#: ../Generic/base.py:1963
 msgid "sheet_dict must be a dictionay"
 msgstr ""
 
-#: ../Generic/base.py:1879 ../Generic/base.py:1886
-msgid "sheet field must be a string"
+#: ../Generic/base.py:1986 ../Generic/base.py:1997
+msgid "sheet field must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:1881
+#: ../Generic/base.py:1990
 msgid "section_dict must be a dictionary"
 msgstr ""
 
-#: ../Generic/base.py:1888
-msgid "sheet section must be a string"
+#: ../Generic/base.py:2001
+msgid "sheet section must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:1890
-msgid "sheet paragraph must be a string"
+#: ../Generic/base.py:2005
+msgid "sheet paragraph must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:2177
-msgid "Owner must be a string"
+#: ../Generic/base.py:2295
+msgid "Owner must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:2193
+#: ../Generic/base.py:2313
 msgid "Invalid Date: $1"
 msgstr ""
 
-#: ../Generic/base.py:2204
-msgid "Comment must be a string"
+#: ../Generic/base.py:2327
+msgid "Comment must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:2220
+#: ../Generic/base.py:2345
 msgid "Budget type must be 1, 2, 3 or 4."
 msgstr ""
 
-#: ../Generic/base.py:2232
+#: ../Generic/base.py:2359
 msgid "Certificate order must be a integer."
 msgstr ""
 
-#: ../Generic/base.py:2247
+#: ../Generic/base.py:2376
 msgid "Budget certificate Date must be a valid Date."
 msgstr ""
 
-#: ../Generic/base.py:2261
+#: ../Generic/base.py:2392
 msgid "Invalid title list format"
 msgstr ""
 
-#: ../Generic/base.py:2290
+#: ../Generic/base.py:2423
 msgid "Invalid Index Title"
 msgstr ""
 
-#: ../Generic/base.py:2327
+#: ../Generic/base.py:2462
 msgid "Decimal Key error"
 msgstr ""
 
-#: ../Generic/base.py:2365
+#: ../Generic/base.py:2500
 msgid "Invalid Percentage key"
 msgstr ""
 
-#: ../Generic/base.py:2488
+#: ../Generic/base.py:2619
+msgid "No-estructured measures. Adding root record"
+msgstr ""
+
+#: ../Generic/base.py:2624
 msgid "Invalid parent code: $1"
 msgstr ""
 
-#: ../Generic/base.py:2491
+#: ../Generic/base.py:2629
 msgid "Invalid child code: $1 $2"
 msgstr ""
 
-#: ../Generic/base.py:2494
-msgid "Invalid position in measure $1, in code $2"
+#: ../Generic/base.py:2634
+msgid "Invalid position in measure $1, in code $2 $3"
 msgstr ""
 
-#: ../Generic/base.py:2502
+#: ../Generic/base.py:2644
 msgid ""
 "Circular Decomposition, parent code: $1, child code: $2, repeated code: $3"
 msgstr ""
 
-#: ../Generic/base.py:2527
+#: ../Generic/base.py:2671
 msgid ""
 "No-estructured measure or empty position. Parent Code: $1, Child code: $2, "
 "Position: $3"
 msgstr ""
 
-#: ../Generic/base.py:2531
+#: ../Generic/base.py:2678
 msgid ""
 "No-estructured measure or empty position. Repeated child in unspecified "
 "position. It is impossible to determine the position. New child is added in "
 "the decomposition. Parent code: $1, Child code: $2, Position: $3"
 msgstr ""
 
-#: ../Generic/base.py:2571 ../Generic/base.py:2583
+#: ../Generic/base.py:2721 ../Generic/base.py:2738
 msgid ""
 "Error: Invalid child position in decomposition. Parent code: $1 Child code: "
 "$2 Position: $3"
 msgstr ""
 
-#: ../Generic/base.py:2577
+#: ../Generic/base.py:2730
 msgid "Error: Empty child code. Parent code: $1 Position: $2"
 msgstr ""
 
-#: ../Generic/base.py:2669
+#: ../Generic/base.py:2837
 msgid "Invalid code"
 msgstr ""
 
-#: ../Generic/base.py:2679
+#: ../Generic/base.py:2849
 msgid "Invalid record: $1"
 msgstr ""
 
-#: ../Generic/base.py:2742
+#: ../Generic/base.py:2915
 msgid "Only can be one root record"
 msgstr ""
 
-#: ../Generic/base.py:2851 ../Generic/base.py:2857
+#: ../Generic/base.py:3026 ../Generic/base.py:3036
 msgid "This record does not exits"
 msgstr ""
 
-#: ../Generic/base.py:2854
+#: ../Generic/base.py:3031
 msgid "Path item must be a integer"
 msgstr ""
 
-#: ../Generic/base.py:2859
+#: ../Generic/base.py:3040
 msgid "Path must be a not empty tuple: $1"
 msgstr ""
 
-#: ../Generic/base.py:2926
-msgid "The sheet code must be a string"
+#: ../Generic/base.py:3108
+msgid "The sheet code must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:2928
-msgid "The sheet title must be a string"
+#: ../Generic/base.py:3112
+msgid "The sheet title must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:2939
+#: ../Generic/base.py:3125
 msgid "The sheet sections must be a dictionary"
 msgstr ""
 
-#: ../Generic/base.py:2945
-msgid "The field code must be a string"
+#: ../Generic/base.py:3133
+msgid "The field code must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:2947
-msgid "The field title must be a string"
+#: ../Generic/base.py:3137
+msgid "The field title must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:2958
+#: ../Generic/base.py:3150
 msgid "The sheet field must be a dictionary"
 msgstr ""
 
-#: ../Generic/base.py:2964
-msgid "The paragraph code must be a string"
+#: ../Generic/base.py:3158
+msgid "The paragraph code must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:2966
-msgid "The paragraph text must be a string"
+#: ../Generic/base.py:3162
+msgid "The paragraph text must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:2977
+#: ../Generic/base.py:3175
 msgid "The paragraph dict must be a dictionary"
 msgstr ""
 
-#: ../Generic/base.py:2983 ../Generic/base.py:3008 ../Generic/base.py:3147
-#: ../Generic/base.py:3171 ../Generic/base.py:3193
-msgid "The record_code code must be a string"
+#: ../Generic/base.py:3184 ../Generic/base.py:3217 ../Generic/base.py:3385
+#: ../Generic/base.py:3414 ../Generic/base.py:3442
+msgid "The record_code code must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:2985
-msgid "The field must be a string"
+#: ../Generic/base.py:3188
+msgid "The field must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:2987
+#: ../Generic/base.py:3192
 msgid "The section dict must be a dictionary"
 msgstr ""
 
-#: ../Generic/base.py:2991
+#: ../Generic/base.py:3198
 msgid ""
 "Error: The budget do not have this record code and can not be added the "
 "sheet text in the field $1. Record Code: $2"
 msgstr ""
 
-#: ../Generic/base.py:3011
-msgid "The filename must be a string"
+#: ../Generic/base.py:3221
+msgid "The filename must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:3015
+#: ../Generic/base.py:3226
 msgid ""
 "Error: The budget do not have the record code $1 and can not be added the "
 "file: $2"
 msgstr ""
 
-#: ../Generic/base.py:3026
-msgid "The company code must be a string"
+#: ../Generic/base.py:3237
+msgid "The company code must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:3028
-msgid "The summary must be a string"
+#: ../Generic/base.py:3245 ../Generic/base.py:3283
+msgid "The name must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:3030 ../Generic/base.py:3058
-msgid "The name must be a string"
-msgstr ""
-
-#: ../Generic/base.py:3032
+#: ../Generic/base.py:3249
 msgid "The name must be a list"
 msgstr ""
 
-#: ../Generic/base.py:3036
+#: ../Generic/base.py:3255
 msgid "The office must be a list"
 msgstr ""
 
-#: ../Generic/base.py:3038
+#: ../Generic/base.py:3259
 msgid "The office must be a 10 items list"
 msgstr ""
 
-#: ../Generic/base.py:3041
-msgid "This office item must be a string"
+#: ../Generic/base.py:3264
+msgid "This office item must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:3045
+#: ../Generic/base.py:3269
 msgid "This office item must be a list"
 msgstr ""
 
-#: ../Generic/base.py:3060
-msgid "The web must be a string"
+#: ../Generic/base.py:3287
+msgid "The web must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:3062
-msgid "The email must be a string"
+#: ../Generic/base.py:3291
+msgid "The email must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:3074
-msgid "The tecnical info code must be a string"
+#: ../Generic/base.py:3305
+msgid "The tecnical info code must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:3076
-msgid "The tecnical info description must be a string"
+#: ../Generic/base.py:3309
+msgid "The tecnical info description must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:3079
-msgid "The tecnical info unit must be a string"
+#: ../Generic/base.py:3313
+msgid "The tecnical info unit must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:3130
-msgid "The label must be a string"
+#: ../Generic/base.py:3366
+msgid "The label must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:3149
-msgid "The parametric select comment must be a string"
+#: ../Generic/base.py:3389
+msgid "The parametric select comment must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:3152
+#: ../Generic/base.py:3393
 msgid ""
 "Error: The budget do not have the record code $1 and can not be added the "
 "Parametric select comment: $2"
 msgstr ""
 
-#: ../Generic/base.py:3159
+#: ../Generic/base.py:3401
 msgid ""
 "Error: The Record $1 is not a Parametric Record and can not have Parametric "
 "comment"
 msgstr ""
 
-#: ../Generic/base.py:3173
-msgid "The summary record must be a string"
+#: ../Generic/base.py:3418
+msgid "The summary record must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:3175
+#: ../Generic/base.py:3422
 msgid ""
 "Error: The budget do not have the record code $1 and can not be seted the "
 "summary: $2"
 msgstr ""
 
-#: ../Generic/base.py:3181
+#: ../Generic/base.py:3429
 msgid ""
 "Error: The Record $1 is not a Parametric Record and can not have Parametric "
 "summary"
 msgstr ""
 
-#: ../Generic/base.py:3195
-msgid "The text record must be a string"
+#: ../Generic/base.py:3446
+msgid "The text record must be a text string"
 msgstr ""
 
-#: ../Generic/base.py:3197
+#: ../Generic/base.py:3450
 msgid ""
 "Error: The budget do not have the record code $1 and can not be seted the "
 "text: $2"
 msgstr ""
 
-#: ../Generic/base.py:3203
+#: ../Generic/base.py:3457
 msgid ""
 "Error: The Record $1 is not a Parametric Record and can not have Parametric "
 "text"
 msgstr ""
 
-#: ../Generic/base.py:3726
+#: ../Generic/base.py:3981
 msgid "Invalid Hierarchy ($1) The hierarchy must be -1, 0, 1, 2"
 msgstr ""
 
-#: ../Generic/base.py:3738
+#: ../Generic/base.py:3987
+msgid "Hierarchy temporarily set to an empty string"
+msgstr ""
+
+#: ../Generic/base.py:3997
 msgid "Invalid type ($1),the type must be (empty string,0,1,2,3)"
 msgstr ""
 
-#: ../Generic/base.py:3749
+#: ../Generic/base.py:4011
 msgid ""
 "Invalid subtype ($1), The subtype must one in (empty string, EA, EU, EC, EF, "
 "OB, PA, PU, H, Q, %, MC, MCr, MM, MS, ME, MCu, MAl, ML, M)"
 msgstr ""
 
-#: ../Generic/fiebdc.py:150
-msgid "Invalid code, it must be a unicode string"
+#: ../Generic/fiebdc.py:156
+msgid "Invalid code, it must be a text string"
 msgstr ""
 
-#: ../Generic/fiebdc.py:157
+#: ../Generic/fiebdc.py:164
 msgid "The code '$1' have invalid characters, replaced by '$2'."
 msgstr ""
 
-#: ../Generic/fiebdc.py:160
-msgid "The code '$1' have invalid characters and can not be encoded in utf8."
+#: ../Generic/fiebdc.py:169
+msgid "The code '$1' have invalid characters and can not be encoded in utf-8."
 msgstr ""
 
-#: ../Generic/fiebdc.py:187
+#: ../Generic/fiebdc.py:206
 msgid "The code '$1' contains special characters repeated."
 msgstr ""
 
-#: ../Generic/fiebdc.py:391
+#: ../Generic/fiebdc.py:411
 msgid "FIEBDC. Unknow record: $1"
 msgstr ""
 
-#: ../Generic/fiebdc.py:410
+#: ../Generic/fiebdc.py:432
 msgid ""
 "The 'V' record (Property and Version) must be the first record in the file "
 "but it is the number: $1"
 msgstr ""
 
-#: ../Generic/fiebdc.py:413
+#: ../Generic/fiebdc.py:437
 msgid "The default values were taken and this V record is ignored"
 msgstr ""
 
-#: ../Generic/fiebdc.py:447
+#: ../Generic/fiebdc.py:472
 msgid "FIEBDC format: $1"
 msgstr ""
 
-#: ../Generic/fiebdc.py:457
+#: ../Generic/fiebdc.py:484
 msgid "FIEBDC file generated by $1"
 msgstr ""
 
-#: ../Generic/fiebdc.py:798
+#: ../Generic/fiebdc.py:825
 msgid "Record C without a valid code"
 msgstr ""
 
-#: ../Generic/fiebdc.py:876 ../Generic/fiebdc.py:888 ../Generic/fiebdc.py:916
+#: ../Generic/fiebdc.py:904 ../Generic/fiebdc.py:917 ../Generic/fiebdc.py:946
 msgid "Incorrect type ($1) in the code $2"
 msgstr ""
 
-#: ../Generic/fiebdc.py:970
+#: ../Generic/fiebdc.py:1001
 msgid ""
 "ValueError loadig the descomposition of the record $1, the factor of the "
 "child $2 must be a float number and can not be $3, seted default value 1.0"
 msgstr ""
 
-#: ../Generic/fiebdc.py:981
+#: ../Generic/fiebdc.py:1013
 msgid ""
 "ValueError loading the descomposition of the record $1, the yield of the "
 "child $2, must be a float number and cannot be $3,  seted default value 1.0"
 msgstr ""
 
-#: ../Generic/fiebdc.py:1070
+#: ../Generic/fiebdc.py:1102
 msgid "Invalid codes in $1 record, codes $2"
 msgstr ""
 
-#: ../Generic/fiebdc.py:1074
+#: ../Generic/fiebdc.py:1107
 msgid "Empty child code in $1 record, codes: $2"
 msgstr ""
 
-#: ../Generic/fiebdc.py:1094
+#: ../Generic/fiebdc.py:1128
 msgid "Invalid path in $1 record, codes $2"
 msgstr ""
 
-#: ../Generic/fiebdc.py:1105
+#: ../Generic/fiebdc.py:1140
 msgid "Invalid Total Measure value in $1 record, codes $2. Total fixed to 0."
 msgstr ""
 
-#: ../Generic/fiebdc.py:1126
+#: ../Generic/fiebdc.py:1162
 msgid ""
 "The comment is not a formula or its have invalid characters, in the $1 "
 "record, codes $2"
 msgstr ""
 
-#: ../Generic/fiebdc.py:1152
+#: ../Generic/fiebdc.py:1189
 msgid "The measure values are not float numbers, code $1"
 msgstr ""
 
-#: ../Generic/fiebdc.py:1452 ../Generic/fiebdc.py:1717
+#: ../Generic/fiebdc.py:1493 ../Generic/fiebdc.py:1761
 msgid "The file $1 do not exist"
 msgstr ""
 
-#: ../Generic/fiebdc.py:1823 ../Generic/fiebdc.py:1830
+#: ../Generic/fiebdc.py:1869 ../Generic/fiebdc.py:1877
 msgid "PyArq hates parametric DLLs"
 msgstr ""
 
-#: ../Generic/fiebdc.py:2028
+#: ../Generic/fiebdc.py:1985
+msgid "Parametric: code:  $1"
+msgstr ""
+
+#: ../Generic/fiebdc.py:1988
+msgid "******* Desconocido *** : $1"
+msgstr ""
+
+#: ../Generic/fiebdc.py:2103
 msgid "Loading file $1"
 msgstr ""
 
-#: ../Generic/fiebdc.py:2049
+#: ../Generic/fiebdc.py:2125
 msgid "FIEBDC character encoding: $1"
 msgstr ""
 
-#: ../Generic/fiebdc.py:2053
+#: ../Generic/fiebdc.py:2129
 msgid ""
 "This Character encoding do not exist in FIEBDC3! Default Character encoding: "
 "$1"
 msgstr ""
 
-#: ../Generic/fiebdc.py:2058
+#: ../Generic/fiebdc.py:2134
 msgid ""
 "This V record dot have a character encoding! Default character encoding: $1"
 msgstr ""
 
-#: ../Generic/fiebdc.py:2063
+#: ../Generic/fiebdc.py:2139
 msgid "Not 'V' record in File! Default character encoding: $1"
 msgstr ""
 
-#: ../Generic/fiebdc.py:2111
+#: ../Generic/fiebdc.py:2187
 msgid "$1 unsuported record type O: Comercial Relationship"
 msgstr ""
 
-#: ../Generic/fiebdc.py:2114
+#: ../Generic/fiebdc.py:2191
 msgid "This file is not a valid FIBDC3 file"
 msgstr ""
 
-#: ../Generic/fiebdc.py:2127
+#: ../Generic/fiebdc.py:2205
 msgid "Testing budget ..."
 msgstr ""
 
-#: ../Generic/fiebdc.py:2146
+#: ../Generic/fiebdc.py:2225
 msgid "End Test"
 msgstr ""
 
-#: ../Generic/fiebdc.py:2230 ../Gtk/gui.py:1038
+#: ../Generic/fiebdc.py:2312 ../Gtk/gui.py:1074
 msgid "Process terminated"
 msgstr ""
 
-#: ../Generic/fiebdc.py:2312
+#: ../Generic/fiebdc.py:2396
 msgid "Time to load: $1 seconds"
 msgstr ""
 
-#: ../Generic/fiebdc.py:2314
+#: ../Generic/fiebdc.py:2398
 msgid "Records/Valid Records: $1/$2"
 msgstr ""
 
-#: ../Gtk/gui.py:83 ../Gtk/gui.py:89
+#: ../Generic/utils.py:154
+msgid "Not a text string, code: $1, type: $2"
+msgstr ""
+
+#: ../Generic/utils.py:168
+msgid "Unicode Error, code: $1"
+msgstr ""
+
+#: ../Generic/utils.py:173
+msgid "Not in cp850, code: $1"
+msgstr ""
+
+#: ../Generic/utils.py:182
+msgid "Control characters in code: $1"
+msgstr ""
+
+#: ../Generic/utils.py:190
+msgid "# in code: $1"
+msgstr ""
+
+#: ../Generic/utils.py:197
+msgid "Empty code"
+msgstr ""
+
+#: ../Gtk/gui.py:103 ../Gtk/gui.py:110
 msgid "The icon file does not exist. '$1'"
 msgstr ""
 
-#: ../Gtk/gui.py:95
+#: ../Gtk/gui.py:117
 msgid "pyArq-Presupuestos running on $1"
 msgstr ""
 
-#: ../Gtk/gui.py:176
+#: ../Gtk/gui.py:200
 msgid "_New window"
 msgstr ""
 
-#: ../Gtk/gui.py:177
+#: ../Gtk/gui.py:201
 msgid "_Close window"
 msgstr ""
 
-#: ../Gtk/gui.py:182
+#: ../Gtk/gui.py:206
 msgid "About"
 msgstr ""
 
-#: ../Gtk/gui.py:185
+#: ../Gtk/gui.py:209
 msgid "_Quit application"
 msgstr ""
 
-#: ../Gtk/gui.py:195
+#: ../Gtk/gui.py:219
 msgid "_Import Fiebdc"
 msgstr ""
 
-#: ../Gtk/gui.py:199 ../Gtk/gui.py:400 ../Gtk/gui.py:955
+#: ../Gtk/gui.py:224 ../Gtk/gui.py:426 ../Gtk/gui.py:990
 msgid "_Close tab"
 msgstr ""
 
-#: ../Gtk/gui.py:203
+#: ../Gtk/gui.py:228
 msgid "_File"
 msgstr ""
 
-#: ../Gtk/gui.py:205
+#: ../Gtk/gui.py:230
 msgid "_Back"
 msgstr ""
 
-#: ../Gtk/gui.py:208
+#: ../Gtk/gui.py:233
 msgid "_Forward"
 msgstr ""
 
-#: ../Gtk/gui.py:211
+#: ../Gtk/gui.py:236
 msgid "_Up Item"
 msgstr ""
 
-#: ../Gtk/gui.py:214
+#: ../Gtk/gui.py:239
 msgid "_Root"
 msgstr ""
 
-#: ../Gtk/gui.py:217
+#: ../Gtk/gui.py:242
 msgid "_Go"
 msgstr ""
 
-#: ../Gtk/gui.py:391 ../Gtk/gui.py:392
+#: ../Gtk/gui.py:417 ../Gtk/gui.py:418
 msgid "Import Fiebdc"
 msgstr ""
 
-#: ../Gtk/gui.py:401 ../Gtk/gui.py:956
+#: ../Gtk/gui.py:427 ../Gtk/gui.py:991
 msgid "Close tab"
 msgstr ""
 
-#: ../Gtk/gui.py:413 ../Gtk/gui.py:414
+#: ../Gtk/gui.py:439 ../Gtk/gui.py:440
 msgid "Back"
 msgstr ""
 
-#: ../Gtk/gui.py:422 ../Gtk/gui.py:423
+#: ../Gtk/gui.py:449 ../Gtk/gui.py:450
 msgid "Forward"
 msgstr ""
 
-#: ../Gtk/gui.py:431 ../Gtk/gui.py:432
+#: ../Gtk/gui.py:458 ../Gtk/gui.py:459
 msgid "Up Item"
 msgstr ""
 
-#: ../Gtk/gui.py:440 ../Gtk/gui.py:441
+#: ../Gtk/gui.py:467 ../Gtk/gui.py:468
 msgid "Root"
 msgstr ""
 
-#: ../Gtk/gui.py:655
+#: ../Gtk/gui.py:684
 msgid "The page is not in the page list"
 msgstr ""
 
-#: ../Gtk/gui.py:792 ../Gtk/gui.py:793
+#: ../Gtk/gui.py:823 ../Gtk/gui.py:824
 msgid "Open File"
 msgstr ""
 
-#: ../Gtk/gui.py:794
+#: ../Gtk/gui.py:825
 msgid "Cancel"
 msgstr ""
 
-#: ../Gtk/gui.py:833
+#: ../Gtk/gui.py:868
 msgid "The file must have 'bc3' extension"
 msgstr ""
 
-#: ../Gtk/gui.py:991
+#: ../Gtk/gui.py:1027
 msgid "Time: 0s"
 msgstr ""
 
-#: ../Gtk/gui.py:1104
+#: ../Gtk/gui.py:1140
 msgid "Time: $1"
 msgstr ""
 
-#: ../Gtk/gui.py:1455
+#: ../Gtk/gui.py:1492
 msgid "The value must be a list"
 msgstr ""
 
-#: ../Gtk/gui.py:1458
+#: ../Gtk/gui.py:1497
 msgid "Incorrect len"
 msgstr ""
 
-#: ../Gtk/gui.py:1486
+#: ../Gtk/gui.py:1528
 msgid "Incorrect item $1"
 msgstr ""
 
-#: ../Gtk/gui.py:1502
+#: ../Gtk/gui.py:1546
 msgid "The budget does not have the path record: $1"
 msgstr ""
 
-#: ../Gtk/gui.py:1865
+#: ../Gtk/gui.py:1911
 msgid "Decomposition"
 msgstr ""
 
-#: ../Gtk/gui.py:1866 ../Gtk/gui.py:2895
+#: ../Gtk/gui.py:1912 ../Gtk/gui.py:2956
 msgid "Description"
 msgstr ""
 
-#: ../Gtk/gui.py:1867 ../Gtk/gui.py:2897
+#: ../Gtk/gui.py:1913 ../Gtk/gui.py:2960
 msgid "Measure"
 msgstr ""
 
-#: ../Gtk/gui.py:1868
+#: ../Gtk/gui.py:1914
 msgid "Sheet of Conditions"
 msgstr ""
 
-#: ../Gtk/gui.py:1869
+#: ../Gtk/gui.py:1915
 msgid "Files"
 msgstr ""
 
-#: ../Gtk/gui.py:1870
+#: ../Gtk/gui.py:1916
 msgid "Companies"
 msgstr ""
 
-#: ../Gtk/gui.py:1950
+#: ../Gtk/gui.py:1964
+msgid "Invalid type of View: $1"
+msgstr ""
+
+#: ../Gtk/gui.py:1998
 msgid "Split View Left/Right"
 msgstr ""
 
-#: ../Gtk/gui.py:1960
+#: ../Gtk/gui.py:2008
 msgid "Split View Top/Bottom"
 msgstr ""
 
-#: ../Gtk/gui.py:1968
+#: ../Gtk/gui.py:2017
 msgid "Disconnect view"
 msgstr ""
 
-#: ../Gtk/gui.py:1971
+#: ../Gtk/gui.py:2021
 msgid "Connect view"
 msgstr ""
 
-#: ../Gtk/gui.py:1984 ../Gtk/gui.py:2081
+#: ../Gtk/gui.py:2034 ../Gtk/gui.py:2131
 msgid "Close view"
 msgstr ""
 
-#: ../Gtk/gui.py:2073
+#: ../Gtk/gui.py:2123
 msgid "Split view Left/Right"
 msgstr ""
 
-#: ../Gtk/gui.py:2077
+#: ../Gtk/gui.py:2127
 msgid "Split view Top/Bottom"
 msgstr ""
 
-#: ../Gtk/gui.py:2112
+#: ../Gtk/gui.py:2163
 msgid "Connect View"
 msgstr ""
 
-#: ../Gtk/gui.py:2118
+#: ../Gtk/gui.py:2169
 msgid "Disconnect View"
 msgstr ""
 
-#: ../Gtk/gui.py:2248
+#: ../Gtk/gui.py:2299
 msgid "The item must be a widget object."
 msgstr ""
 
-#: ../Gtk/gui.py:2256
+#: ../Gtk/gui.py:2309
 msgid "Invalid orientation."
 msgstr ""
 
-#: ../Gtk/gui.py:2628 ../Gtk/gui.py:3256 ../Gtk/gui.py:4674
+#: ../Gtk/gui.py:2683 ../Gtk/gui.py:3321 ../Gtk/gui.py:4756
 msgid "Argument must be a Budget object"
 msgstr ""
 
-#: ../Gtk/gui.py:2892 ../Gtk/gui.py:4739
+#: ../Gtk/gui.py:2952 ../Gtk/gui.py:4823
 msgid "Code"
 msgstr ""
 
-#: ../Gtk/gui.py:2893
+#: ../Gtk/gui.py:2954
 msgid "Unit"
 msgstr ""
 
-#: ../Gtk/gui.py:2899
+#: ../Gtk/gui.py:2962
 msgid "Price"
 msgstr ""
 
-#: ../Gtk/gui.py:2901
+#: ../Gtk/gui.py:2964
 msgid "Amount"
 msgstr ""
 
-#: ../Gtk/gui.py:2912 ../Gtk/gui.py:3528
+#: ../Gtk/gui.py:2975 ../Gtk/gui.py:3598
 msgid "Invalid path"
 msgstr ""
 
-#: ../Gtk/gui.py:3261
+#: ../Gtk/gui.py:3328
 msgid "Record path must be a tuple"
 msgstr ""
 
-#: ../Gtk/gui.py:3509 ../Gtk/gui.py:4754 ../Gtk/gui.py:5066
+#: ../Gtk/gui.py:3579 ../Gtk/gui.py:4838 ../Gtk/gui.py:5154
 msgid "Type"
 msgstr ""
 
-#: ../Gtk/gui.py:3510
+#: ../Gtk/gui.py:3580
 msgid "Comment"
 msgstr ""
 
-#: ../Gtk/gui.py:3511
+#: ../Gtk/gui.py:3581
 msgid ""
 "N\n"
 "(a)"
 msgstr ""
 
-#: ../Gtk/gui.py:3512
+#: ../Gtk/gui.py:3582
 msgid ""
 "Length\n"
 "(b)"
 msgstr ""
 
-#: ../Gtk/gui.py:3513
+#: ../Gtk/gui.py:3583
 msgid ""
 "Width\n"
 "(c)"
 msgstr ""
 
-#: ../Gtk/gui.py:3514
+#: ../Gtk/gui.py:3584
 msgid ""
 "Height\n"
 "(d)"
 msgstr ""
 
-#: ../Gtk/gui.py:3515
+#: ../Gtk/gui.py:3585
 msgid "Formula"
 msgstr ""
 
-#: ../Gtk/gui.py:3516
+#: ../Gtk/gui.py:3586
 #, python-format
 msgid ""
 "Parcial\n"
 "[%s]"
 msgstr ""
 
-#: ../Gtk/gui.py:3517
+#: ../Gtk/gui.py:3587
 msgid "Subtotal"
 msgstr ""
 
-#: ../Gtk/gui.py:3537
+#: ../Gtk/gui.py:3609
 msgid "measure must be a Measure object. Type: $1"
 msgstr ""
 
-#: ../Gtk/gui.py:3835 ../Gtk/gui.py:3856
+#: ../Gtk/gui.py:3909 ../Gtk/gui.py:3931
 msgid "Description text of the record $1"
 msgstr ""
 
-#: ../Gtk/gui.py:4010
+#: ../Gtk/gui.py:4086
 msgid "Sheet of Conditions of the record $1"
 msgstr ""
 
-#: ../Gtk/gui.py:4031
+#: ../Gtk/gui.py:4108
 msgid "Field"
 msgstr ""
 
-#: ../Gtk/gui.py:4054
+#: ../Gtk/gui.py:4132
 msgid "Section"
 msgstr ""
 
-#: ../Gtk/gui.py:4214
+#: ../Gtk/gui.py:4295
 msgid "Sheet2 of Conditions of the record $1"
 msgstr ""
 
-#: ../Gtk/gui.py:4740
+#: ../Gtk/gui.py:4824
 msgid "Code that define the company"
 msgstr ""
 
-#: ../Gtk/gui.py:4741
+#: ../Gtk/gui.py:4825
 msgid "Summary"
 msgstr ""
 
-#: ../Gtk/gui.py:4742
+#: ../Gtk/gui.py:4826
 msgid "Summary of the company name"
 msgstr ""
 
-#: ../Gtk/gui.py:4743 ../Gtk/gui.py:4759
+#: ../Gtk/gui.py:4827 ../Gtk/gui.py:4843
 msgid "Name"
 msgstr ""
 
-#: ../Gtk/gui.py:4744
+#: ../Gtk/gui.py:4828
 msgid "Complete name"
 msgstr ""
 
-#: ../Gtk/gui.py:4745
+#: ../Gtk/gui.py:4829
 msgid "CIF"
 msgstr ""
 
-#: ../Gtk/gui.py:4746
+#: ../Gtk/gui.py:4830
 msgid "Fiscal identifier number"
 msgstr ""
 
-#: ../Gtk/gui.py:4747
+#: ../Gtk/gui.py:4831
 msgid "Web"
 msgstr ""
 
-#: ../Gtk/gui.py:4748
+#: ../Gtk/gui.py:4832
 msgid "Company web page"
 msgstr ""
 
-#: ../Gtk/gui.py:4749
+#: ../Gtk/gui.py:4833
 msgid "Email"
 msgstr ""
 
-#: ../Gtk/gui.py:4750
+#: ../Gtk/gui.py:4834
 msgid "Company email"
 msgstr ""
 
-#: ../Gtk/gui.py:4755
+#: ../Gtk/gui.py:4839
 msgid ""
 "Type of Office:\n"
 "                           C: Central office\n"
@@ -1028,130 +1059,130 @@
 "                           R: Performer"
 msgstr ""
 
-#: ../Gtk/gui.py:4760
+#: ../Gtk/gui.py:4844
 msgid "Office name"
 msgstr ""
 
-#: ../Gtk/gui.py:4761
+#: ../Gtk/gui.py:4845
 msgid "Address"
 msgstr ""
 
-#: ../Gtk/gui.py:4762
+#: ../Gtk/gui.py:4846
 msgid "Postal code"
 msgstr ""
 
-#: ../Gtk/gui.py:4763
+#: ../Gtk/gui.py:4847
 msgid "Town"
 msgstr ""
 
-#: ../Gtk/gui.py:4764
+#: ../Gtk/gui.py:4848
 msgid "Province"
 msgstr ""
 
-#: ../Gtk/gui.py:4765
+#: ../Gtk/gui.py:4849
 msgid "Country"
 msgstr ""
 
-#: ../Gtk/gui.py:4766
+#: ../Gtk/gui.py:4850
 msgid "Phone"
 msgstr ""
 
-#: ../Gtk/gui.py:4767
+#: ../Gtk/gui.py:4851
 msgid "Phone numbers of the office"
 msgstr ""
 
-#: ../Gtk/gui.py:4768
+#: ../Gtk/gui.py:4852
 msgid "Fax"
 msgstr ""
 
-#: ../Gtk/gui.py:4769
+#: ../Gtk/gui.py:4853
 msgid "Fax numbers of the office"
 msgstr ""
 
-#: ../Gtk/gui.py:4770
+#: ../Gtk/gui.py:4854
 msgid "Contact person"
 msgstr ""
 
-#: ../Gtk/gui.py:4771
+#: ../Gtk/gui.py:4855
 msgid "Contact persons in the office"
 msgstr ""
 
-#: ../Gtk/gui.py:4775
+#: ../Gtk/gui.py:4859
 msgid "Unknow Option Type"
 msgstr ""
 
-#: ../Gtk/gui.py:5002
+#: ../Gtk/gui.py:5090
 msgid "Boolean"
 msgstr ""
 
-#: ../Gtk/gui.py:5003
+#: ../Gtk/gui.py:5091
 msgid "Integer"
 msgstr ""
 
-#: ../Gtk/gui.py:5004
+#: ../Gtk/gui.py:5092
 msgid "Text"
 msgstr ""
 
-#: ../Gtk/gui.py:5005
+#: ../Gtk/gui.py:5093
 msgid "Color"
 msgstr ""
 
-#: ../Gtk/gui.py:5006
+#: ../Gtk/gui.py:5094
 msgid "List"
 msgstr ""
 
-#: ../Gtk/gui.py:5040
+#: ../Gtk/gui.py:5128
 msgid "Option name"
 msgstr ""
 
-#: ../Gtk/gui.py:5053
+#: ../Gtk/gui.py:5141
 msgid "Value"
 msgstr ""
 
-#: ../Gtk/gui.py:5094
+#: ../Gtk/gui.py:5182
 msgid "Description:"
 msgstr ""
 
-#: ../Gtk/gui.py:5258
+#: ../Gtk/gui.py:5343
 msgid "Option values must be strings"
 msgstr ""
 
-#: ../Gtk/gui.py:5260
+#: ../Gtk/gui.py:5345
 msgid "Option must be a tuple with 4 items"
 msgstr ""
 
-#: ../Gtk/gui.py:5262
+#: ../Gtk/gui.py:5347
 msgid "Option list must be a list"
 msgstr ""
 
-#: ../Gtk/gui.py:5282
+#: ../Gtk/gui.py:5367
 msgid "Icorrect type, must be boolean"
 msgstr ""
 
-#: ../Gtk/gui.py:5287
+#: ../Gtk/gui.py:5372
 msgid "Icorrect type, must be integer"
 msgstr ""
 
-#: ../Gtk/gui.py:5300
+#: ../Gtk/gui.py:5385
 msgid "Icorrect type, must be string"
 msgstr ""
 
-#: ../Gtk/gui.py:5313
+#: ../Gtk/gui.py:5398
 msgid "Icorrect type, must be list"
 msgstr ""
 
-#: ../Gtk/gui.py:5317
+#: ../Gtk/gui.py:5402
 msgid "Icorrect type, must be a parseable color"
 msgstr ""
 
-#: ../Gtk/gui.py:5325
+#: ../Gtk/gui.py:5410
 msgid "Type must be boolean, integer, string or color"
 msgstr ""
 
-#: ../Gtk/gui.py:5328
+#: ../Gtk/gui.py:5413
 msgid "Value must be in the option dict"
 msgstr ""
 
-#: ../Gtk/gui.py:5331
+#: ../Gtk/gui.py:5416
 msgid "Values must be a dict"
 msgstr ""
--- a/pyArq-Presupuestos.py	Mon May 20 13:18:33 2019 +0200
+++ b/pyArq-Presupuestos.py	Tue Jun 18 17:50:23 2019 +0200
@@ -20,6 +20,11 @@
 ## along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 # Modules
+
+# python 2/3 compatibility
+from __future__ import absolute_import, division, print_function, unicode_literals
+from builtins import str as text
+
 import sys
 import getopt
 import gettext
@@ -76,7 +81,7 @@
             _run_gtk()
     except getopt.error as err:  
         # output error
-        print (str(err))
+        print (txt(err))
 
 # Run pyArq-Presupuestos
 if __name__ == "__main__":