Adding support for internationalization
authorlaurent
Mon, 27 Jul 2009 16:29:59 +0200
changeset 580 2ae92a99ac10
parent 577 0bb82be64630
child 581 dc35cf4ed127
Adding support for internationalization
objdictgen/commondialogs.py
objdictgen/doc_index/DS301_index.py
objdictgen/eds_utils.py
objdictgen/gen_cfile.py
objdictgen/i18n/README
objdictgen/i18n/app.fil
objdictgen/i18n/messages.pot
objdictgen/i18n/mki18n.py
objdictgen/i18n/objdictgen_fr_FR.po
objdictgen/i18n/objdictgen_zh_CN.po
objdictgen/locale/fr_FR/LC_MESSAGES/objdictgen.mo
objdictgen/locale/zh_CN/LC_MESSAGES/objdictgen.mo
objdictgen/networkedit.py
objdictgen/nodelist.py
objdictgen/nodemanager.py
objdictgen/objdictedit.py
objdictgen/objdictgen.py
objdictgen/subindextable.py
--- a/objdictgen/commondialogs.py	Mon Jul 20 16:11:20 2009 +0200
+++ b/objdictgen/commondialogs.py	Mon Jul 27 16:29:59 2009 +0200
@@ -109,11 +109,11 @@
         wx.Dialog.__init__(self, id=ID_COMMUNICATIONDIALOG,
               name='CommunicationDialog', parent=prnt, pos=wx.Point(234, 216),
               size=wx.Size(726, 437), style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER,
-              title='Edit Communication Profile')
+              title=_('Edit Communication Profile'))
         self.SetClientSize(wx.Size(726, 437))
 
         self.staticText1 = wx.StaticText(id=ID_COMMUNICATIONDIALOGSTATICTEXT1,
-              label='Possible Profile Indexes:', name='staticText1',
+              label=_('Possible Profile Indexes:'), name='staticText1',
               parent=self, pos=wx.Point(0, 0), size=wx.Size(0,
               17), style=0)
 
@@ -137,7 +137,7 @@
               id=ID_COMMUNICATIONDIALOGUNSELECT)
 
         self.staticText2 = wx.StaticText(id=ID_COMMUNICATIONDIALOGSTATICTEXT2,
-              label='Current Profile Indexes:', name='staticText2',
+              label=_('Current Profile Indexes:'), name='staticText2',
               parent=self, pos=wx.Point(0, 0), size=wx.Size(0,
               17), style=0)
 
@@ -272,23 +272,23 @@
         wx.Dialog.__init__(self, id=ID_MAPVARIABLEDIALOG,
               name='CommunicationDialog', parent=prnt, pos=wx.Point(376, 223),
               size=wx.Size(444, 186), style=wx.DEFAULT_DIALOG_STYLE,
-              title='Add Map Variable')
+              title=_('Add Map Variable'))
         self.SetClientSize(wx.Size(444, 186))
 
         self.staticText1 = wx.StaticText(id=ID_MAPVARIABLEDIALOGSTATICTEXT1,
-              label='Index:', name='staticText1', parent=self,
+              label=_('Index:'), name='staticText1', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
 
         self.staticText2 = wx.StaticText(id=ID_MAPVARIABLEDIALOGSTATICTEXT2,
-              label='Type:', name='staticText2', parent=self,
+              label=_('Type:'), name='staticText2', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
 
         self.staticText3 = wx.StaticText(id=ID_MAPVARIABLEDIALOGSTATICTEXT3,
-              label='Name:', name='staticText3', parent=self,
+              label=_('Name:'), name='staticText3', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
 
         self.staticText4 = wx.StaticText(id=ID_MAPVARIABLEDIALOGSTATICTEXT4,
-              label='Number:', name='staticText4', parent=self,
+              label=_('Number:'), name='staticText4', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 16), style=0)
 
         self.radioButton1 = wx.RadioButton(id=ID_MAPVARIABLEDIALOGRADIOBUTTON1,
@@ -318,7 +318,7 @@
         
         self.IndexName = wx.TextCtrl(id=ID_MAPVARIABLEDIALOGINDEXNAME,
               name='IndexName', parent=self, pos=wx.Point(0, 0),
-              size=wx.Size(0, 24), style=0, value='Undefined')
+              size=wx.Size(0, 24), style=0, value=_('Undefined'))
         
         self.Number = wx.TextCtrl(id=ID_MAPVARIABLEDIALOGNUMBER,
               name='Number', parent=self, pos=wx.Point(0, 0),
@@ -350,26 +350,22 @@
         try:
             int(self.Index.GetValue(), 16)
         except:
-            error.append("Index")
+            error.append(_("Index"))
         if self.radioButton2.GetValue() or self.radioButton3.GetValue():
             try:
                 int(self.Number.GetValue())
             except:
-                error.append("Number")
+                error.append(_("Number"))
         if len(error) > 0:
             text = ""
-            if len(error) > 1:
-                suffix = "s"
-            else:
-                suffix = ""
             for i, item in enumerate(error):
                 if i == 0:
                     text += item
                 elif i == len(error) - 1:
-                    text += " and %s"%item
+                    text += (" and %s")%item + _(" must be integers!")
                 else:
-                    text += ", %s"%item
-            message = wx.MessageDialog(self, "Form isn't valid. %s must be integer%s!"%(text,suffix), "Error", wx.OK|wx.ICON_ERROR)
+                    text += _(", %s")%item + _(" must be integer!")
+            message = wx.MessageDialog(self, _("Form isn't valid. %s")%text, _("Error"), wx.OK|wx.ICON_ERROR)
             message.ShowModal()
             message.Destroy()
         else:
@@ -476,11 +472,11 @@
     def _init_ctrls(self, prnt):
         wx.Dialog.__init__(self, id=ID_USERTYPEDIALOG, name='UserTypeDialog',
               parent=prnt, pos=wx.Point(376, 223), size=wx.Size(444, 210),
-              style=wx.DEFAULT_DIALOG_STYLE, title='Add User Type')
+              style=wx.DEFAULT_DIALOG_STYLE, title=_('Add User Type'))
         self.SetClientSize(wx.Size(444, 210))
 
         self.staticText1 = wx.StaticText(id=ID_USERTYPEDIALOGSTATICTEXT1,
-              label='Type:', name='staticText1', parent=self,
+              label=_('Type:'), name='staticText1', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
 
         self.Type = wx.Choice(choices=[], id=ID_USERTYPEDIALOGTYPE,
@@ -494,11 +490,11 @@
               size=wx.Size(0, 0), style=wx.TAB_TRAVERSAL)
 
         self.staticBox1 = wx.StaticBox(id=ID_USERTYPEDIALOGSTATICBOX1,
-              label='Values', name='staticBox1', parent=self,
+              label=_('Values'), name='staticBox1', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 0), style=0)
 
         self.staticText2 = wx.StaticText(id=ID_USERTYPEDIALOGSTATICTEXT2,
-              label='Minimum:', name='staticText2', parent=self,
+              label=_('Minimum:'), name='staticText2', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(80, 17), style=0)
 
         self.Min = wx.TextCtrl(id=ID_USERTYPEDIALOGMIN, name='Min',
@@ -506,7 +502,7 @@
               style=wx.TE_RIGHT, value='0')
 
         self.staticText3 = wx.StaticText(id=ID_USERTYPEDIALOGSTATICTEXT3,
-              label='Maximum:', name='staticText3', parent=self,
+              label=_('Maximum:'), name='staticText3', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(80, 17), style=0)
 
         self.Max = wx.TextCtrl(id=ID_USERTYPEDIALOGMAX, name='Max',
@@ -514,7 +510,7 @@
               style=wx.TE_RIGHT, value='0')
 
         self.staticText4 = wx.StaticText(id=ID_USERTYPEDIALOGSTATICTEXT4,
-              label='Length:', name='staticText4', parent=self,
+              label=_('Length:'), name='staticText4', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(80, 17), style=0)
 
         self.Length = wx.TextCtrl(id=ID_USERTYPEDIALOGLENGTH, name='Length',
@@ -534,8 +530,7 @@
     def OnOK(self, event):
         error = []
         good = True
-        firstmessage = ""
-        secondmessage = ""
+        message = None
         name = self.Type.GetStringSelection()
         if name != "":
             valuetype = self.TypeDictionary[name][1]
@@ -543,36 +538,32 @@
                 try:
                     int(self.Min.GetValue(), 16)
                 except:
-                    error.append("Minimum")
+                    error.append(_("Minimum"))
                     good = False
                 try:
                     int(self.Max.GetValue(), 16)
                 except:
-                    error.append("Maximum")
+                    error.append(_("Maximum"))
                     good = False
             elif valuetype == 1:
                 try:
                     int(self.Length.GetValue(), 16)
                 except:
-                    error.append("Length")
+                    error.append(_("Length"))
                     good = False
             if len(error) > 0:
-                secondmessage = ". "
+                message = ""
                 for i, item in enumerate(error):
                     if i == 0:
-                        secondmessage += item
+                        message += item
                     elif i == len(error) - 1:
-                        secondmessage += " and %s"%item
+                        message += _(" and %s")%item + _(" must be integers!")
                     else:
-                        secondmessage += ", %s"%item
-                secondmessage += " must be integer"
-                if len(error) > 1:
-                    secondmessage += "s"
+                        message += _(", %s")%item + _(" must be integer!")
         else:
-            firstmessage = ". A type must be selected"
-            good = False
-        if not good:
-            message = wx.MessageDialog(self, "Form isn't valid%s%s%s!"%(firstmessage,secondmessage), "Error", wx.OK|wx.ICON_ERROR)
+            message = _("A type must be selected!")
+        if message is not None:
+            message = wx.MessageDialog(self, _("Form isn't valid. %s")%(firstmessage,secondmessage), _("Error"), wx.OK|wx.ICON_ERROR)
             message.ShowModal()
             message.Destroy()
         else:
@@ -652,6 +643,11 @@
  ID_NODEINFOSDIALOGSTATICTEXT5, 
 ] = [wx.NewId() for _init_ctrls in range(11)]
 
+def GetNodeTypes():
+    _ = lambda x : x
+    return [_("master"), _("slave")]
+NODE_TYPES_DICT = dict([(_(node_type), node_type) for node_type in GetNodeTypes()])
+
 class NodeInfosDialog(wx.Dialog):
     def _init_coll_flexGridSizer1_Items(self, parent):
         parent.AddSizer(self.MainSizer, 0, border=20, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT)
@@ -691,11 +687,11 @@
         wx.Dialog.__init__(self, id=ID_NODEINFOSDIALOG,
               name='NodeInfosDialog', parent=prnt, pos=wx.Point(376, 223),
               size=wx.Size(300, 280), style=wx.DEFAULT_DIALOG_STYLE,
-              title='Node Infos')
+              title=_('Node infos'))
         self.SetClientSize(wx.Size(300, 280))
 
         self.staticText1 = wx.StaticText(id=ID_NODEINFOSDIALOGSTATICTEXT1,
-              label='Name:', name='staticText1', parent=self,
+              label=_('Name:'), name='staticText1', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
 
         self.NodeName = wx.TextCtrl(id=ID_NODEINFOSDIALOGNAME, name='NodeName',
@@ -703,7 +699,7 @@
               style=0, value='')
 
         self.staticText2 = wx.StaticText(id=ID_NODEINFOSDIALOGSTATICTEXT2,
-              label='Node ID:', name='staticText2', parent=self,
+              label=_('Node ID:'), name='staticText2', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
 
         self.NodeID = wx.TextCtrl(id=ID_NODEINFOSDIALOGNODEID, name='NodeID',
@@ -711,7 +707,7 @@
               style=wx.TE_RIGHT, value='')
 
         self.staticText3 = wx.StaticText(id=ID_NODEINFOSDIALOGSTATICTEXT3,
-              label='Type:', name='staticText3', parent=self,
+              label=_('Type:'), name='staticText3', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
 
         self.Type = wx.Choice(choices=[], id=ID_NODEINFOSDIALOGTYPE,
@@ -719,7 +715,7 @@
               size=wx.Size(0, 25), style=0)
 
         self.staticText4 = wx.StaticText(id=ID_NODEINFOSDIALOGSTATICTEXT4,
-              label='Default String Size:', name='staticText4', parent=self,
+              label=_('Default String Size:'), name='staticText4', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
 
         self.DefaultStringSize = wx.SpinCtrl(id=ID_NODEINFOSDIALOGDEFAULTSTRINGSIZE, 
@@ -727,7 +723,7 @@
               size=wx.Size(0, 25), style=wx.TE_RIGHT)
         
         self.staticText5 = wx.StaticText(id=ID_NODEINFOSDIALOGSTATICTEXT5,
-              label='Description:', name='staticText5', parent=self,
+              label=_('Description:'), name='staticText5', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
 
         self.Description = wx.TextCtrl(id=ID_NODEINFOSDIALOGDESCRIPTION, 
@@ -745,8 +741,8 @@
         self.staticText2.Hide()
         self.NodeID.Hide()
         
-        self.Type.Append("master")
-        self.Type.Append("slave")
+        for node_type in GetNodeTypes():
+            self.Type.Append(_(node_type))
 
     def OnOK(self, event):
         name = self.NodeName.GetValue()
@@ -756,14 +752,14 @@
             for item in name.split("_"):
                 good &= item.isalnum()
             if not good:
-                message = "Node name can't be undefined or start with a digit and must be composed of alphanumerical characters or underscore!"
+                message = _("Node name can't be undefined or start with a digit and must be composed of alphanumerical characters or underscore!")
         if message != "":
             try:
                 nodeid = int(self.NodeID.GetValue(), 16)
             except:
-                message = "Node ID must be integer!"
+                message = _("Node ID must be integer!")
         if message != "":
-            message = wx.MessageDialog(self, message, "ERROR", wx.OK|wx.ICON_ERROR)
+            message = wx.MessageDialog(self, message, _("ERROR"), wx.OK|wx.ICON_ERROR)
             message.ShowModal()
             message.Destroy()
             self.NodeName.SetFocus()
@@ -773,14 +769,14 @@
     def SetValues(self, name, id, type, description, defaultstringsize):
         self.NodeName.SetValue(name)
         self.NodeID.SetValue("0x%02X"%id)
-        self.Type.SetStringSelection(type)
+        self.Type.SetStringSelection(_(type))
         self.Description.SetValue(description)
         self.DefaultStringSize.SetValue(defaultstringsize)
 
     def GetValues(self):
         name = self.NodeName.GetValue()
         nodeid = int(self.NodeID.GetValue(), 16)
-        type = self.Type.GetStringSelection()
+        type = NODE_TYPES_DICT[self.Type.GetStringSelection()]
         description = self.Description.GetValue()
         defaultstringsize = self.DefaultStringSize.GetValue()
         return name, nodeid, type, description, defaultstringsize
@@ -894,23 +890,23 @@
         wx.Dialog.__init__(self, id=ID_CREATENODEDIALOG,
               name='CreateNodeDialog', parent=prnt, pos=wx.Point(376, 223),
               size=wx.Size(450, 350), style=wx.DEFAULT_DIALOG_STYLE,
-              title='Create a new Node')
+              title=_('Create a new Node'))
         self.SetClientSize(wx.Size(450, 350))
 
         self.staticText1 = wx.StaticText(id=ID_CREATENODEDIALOGSTATICTEXT1,
-              label='Type:', name='staticText1', parent=self,
+              label=_('Type:'), name='staticText1', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
 
         self.staticText2 = wx.StaticText(id=ID_CREATENODEDIALOGSTATICTEXT2,
-              label='Name:', name='staticText2', parent=self,
+              label=_('Name:'), name='staticText2', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
 
         self.staticText3 = wx.StaticText(id=ID_CREATENODEDIALOGSTATICTEXT3,
-              label='Node ID:', name='staticText3', parent=self,
+              label=_('Node ID:'), name='staticText3', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
 
         self.staticText4 = wx.StaticText(id=ID_CREATENODEDIALOGSTATICTEXT4,
-              label='Profile:', name='staticText4', parent=self,
+              label=_('Profile:'), name='staticText4', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
 
         self.Type = wx.Choice(choices=[], id=ID_CREATENODEDIALOGTYPE,
@@ -932,58 +928,58 @@
               id=ID_CREATENODEDIALOGPROFILE)
 
         self.staticText5 = wx.StaticText(id=ID_CREATENODEDIALOGSTATICTEXT5,
-              label='Network Management:', name='staticText5',
+              label=_('Network Management:'), name='staticText5',
               parent=self, pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
 
         self.NMT_None = wx.RadioButton(id=ID_CREATENODEDIALOGNMT_NONE,
-              label='None', name='NMT_None', parent=self,
+              label=_('None'), name='NMT_None', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 24), style=wx.RB_GROUP)
         self.NMT_None.SetValue(True)
 
         self.NMT_NodeGuarding = wx.RadioButton(id=ID_CREATENODEDIALOGNMT_NODEGUARDING,
-              label='Node Guarding', name='NMT_NodeGuarding', parent=self, 
+              label=_('Node Guarding'), name='NMT_NodeGuarding', parent=self, 
               pos=wx.Point(0, 0), size=wx.Size(0, 24), style=0)
         self.NMT_NodeGuarding.SetValue(False)
 
         self.NMT_Heartbeat = wx.RadioButton(id=ID_CREATENODEDIALOGNMT_HEARTBEAT,
-              label='Heartbeat', name='NMT_Heartbeat', parent=self,
+              label=_('Heartbeat'), name='NMT_Heartbeat', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 24), style=0)
         self.NMT_Heartbeat.SetValue(False)
 
         self.staticText6 = wx.StaticText(id=ID_CREATENODEDIALOGSTATICTEXT6,
-              label='Options:', name='staticText6', parent=self,
+              label=_('Options:'), name='staticText6', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
 
         self.DS302 = wx.CheckBox(id=ID_CREATENODEDIALOGGENSYNC,
-              label='DS-302 Profile', name='DS302', parent=self,
+              label=_('DS-302 Profile'), name='DS302', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 24), style=0)
         self.DS302.SetValue(False)
         #self.DS302.Enable(False)
 
         self.GenSYNC = wx.CheckBox(id=ID_CREATENODEDIALOGGENSYNC,
-              label='Generate SYNC', name='GenSYNC', parent=self,
+              label=_('Generate SYNC'), name='GenSYNC', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 24), style=0)
         self.GenSYNC.SetValue(False)
 
         self.Emergency = wx.CheckBox(id=ID_CREATENODEDIALOGEMERGENCY,
-              label='Emergency support', name='Emergency',
+              label=_('Emergency support'), name='Emergency',
               parent=self, pos=wx.Point(0, 0), size=wx.Size(0, 24), style=0)
         self.Emergency.SetValue(False)
 
         self.SaveConfig = wx.CheckBox(id=ID_CREATENODEDIALOGSAVECONFIG,
-              label='Save Configuration', name='SaveConfig', parent=self, 
+              label=_('Save Configuration'), name='SaveConfig', parent=self, 
               pos=wx.Point(0, 0), size=wx.Size(0, 24), style=0)
         self.SaveConfig.SetValue(False)
         self.SaveConfig.Enable(False)
 
         self.StoreEDS = wx.CheckBox(id=ID_CREATENODEDIALOGSTOREEDS,
-              label='Store EDS', name='StoreEDS', parent=self,
+              label=_('Store EDS'), name='StoreEDS', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 24), style=0)
         self.StoreEDS.SetValue(False)
         self.StoreEDS.Hide()
 
         self.staticText7 = wx.StaticText(id=ID_CREATENODEDIALOGSTATICTEXT7,
-              label='Description:', name='staticText7', parent=self,
+              label=_('Description:'), name='staticText7', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
 
         self.Description = wx.TextCtrl(id=ID_CREATENODEDIALOGDESCRIPTION, 
@@ -1006,12 +1002,12 @@
         self.NodeID.Hide()
         
         self.NodeID.SetValue("0x00")
-        self.Type.Append("master")
-        self.Type.Append("slave")
-        self.Type.SetStringSelection("slave")
+        for node_type in GetNodeTypes():
+            self.Type.Append(_(node_type))
+        self.Type.SetStringSelection(_("slave"))
         self.Description.SetValue("")
         self.ListProfile = {"None" : ""}
-        self.Profile.Append("None")
+        self.Profile.Append(_("None"))
         self.Directory = os.path.join(ScriptDirectory, "config")
         listfiles = os.listdir(self.Directory)
         listfiles.sort()
@@ -1020,8 +1016,8 @@
             if os.path.isfile(os.path.join(self.Directory, item)) and extend == ".prf" and name != "DS-302":
                 self.ListProfile[name] = os.path.join(self.Directory, item)
                 self.Profile.Append(name)
-        self.Profile.Append("Other")
-        self.Profile.SetStringSelection("None")
+        self.Profile.Append(_("Other"))
+        self.Profile.SetStringSelection(_("None"))
         self.NodeName.SetFocus()
         
     def OnOK(self, event):
@@ -1032,14 +1028,14 @@
             for item in name.split("_"):
                 good &= item.isalnum()
             if not good:
-                message = "Node name can't be undefined or start with a digit and must be composed of alphanumerical characters or underscore!"
+                message = _("Node name can't be undefined or start with a digit and must be composed of alphanumerical characters or underscore!")
         if message != "":
             try:
                 nodeid = int(self.NodeID.GetValue(), 16)
             except:
-                message = "Node ID must be an integer!"
+                message = _("Node ID must be integer!")
         if message != "":
-            message = wx.MessageDialog(self, message, "ERROR", wx.OK|wx.ICON_ERROR)
+            message = wx.MessageDialog(self, message, _("ERROR"), wx.OK|wx.ICON_ERROR)
             message.ShowModal()
             message.Destroy()
             self.NodeName.SetFocus()
@@ -1051,12 +1047,14 @@
         nodeid = 0
         if self.NodeID.GetValue() != "":
             nodeid = int(self.NodeID.GetValue(), 16)
-        type = self.Type.GetStringSelection()
+        type = NODE_TYPES_DICT[self.Type.GetStringSelection()]
         description = self.Description.GetValue()
         return name, nodeid, type, description
 
     def GetProfile(self):
         name = self.Profile.GetStringSelection()
+        if name == _("None"):
+            name = "None"
         return name, self.ListProfile[name]
 
     def GetNMTManagement(self):
@@ -1083,8 +1081,8 @@
         return options
 
     def OnProfileChoice(self, event):
-        if self.Profile.GetStringSelection() == "Other":
-            dialog = wx.FileDialog(self, "Choose a file", self.Directory, "",  "OD Profile files (*.prf)|*.prf|All files|*.*", wx.OPEN|wx.CHANGE_DIR)
+        if self.Profile.GetStringSelection() == _("Other"):
+            dialog = wx.FileDialog(self, _("Choose a file"), self.Directory, "",  _("OD Profile files (*.prf)|*.prf|All files|*.*"), wx.OPEN|wx.CHANGE_DIR)
             dialog.ShowModal()
             filepath = dialog.GetPath()
             dialog.Destroy()
@@ -1095,7 +1093,7 @@
                 self.Profile.Insert(name, length - 2)
                 self.Profile.SetStringSelection(name)
             else:
-                self.Profile.SetStringSelection("None")
+                self.Profile.SetStringSelection(_("None"))
         event.Skip()
 
 
@@ -1151,11 +1149,11 @@
         wx.Dialog.__init__(self, id=ID_ADDSLAVEDIALOG,
               name='AddSlaveDialog', parent=prnt, pos=wx.Point(376, 223),
               size=wx.Size(300, 250), style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER,
-              title='Add a slave to nodelist')
+              title=_('Add a slave to nodelist'))
         self.SetClientSize(wx.Size(300, 250))
 
         self.staticText1 = wx.StaticText(id=ID_ADDSLAVEDIALOGSTATICTEXT1,
-              label='Slave Name:', name='staticText1', parent=self,
+              label=_('Slave Name:'), name='staticText1', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
 
         self.SlaveName = wx.TextCtrl(id=ID_ADDSLAVEDIALOGSLAVENAME,
@@ -1163,7 +1161,7 @@
               size=wx.Size(0, 24), style=0)
 
         self.staticText2 = wx.StaticText(id=ID_ADDSLAVEDIALOGSTATICTEXT2,
-              label='Slave Node ID:', name='staticText2', parent=self,
+              label=_('Slave Node ID:'), name='staticText2', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
 
         self.SlaveNodeID = wx.TextCtrl(id=ID_ADDSLAVEDIALOGSLAVENODEID,
@@ -1171,14 +1169,14 @@
               size=wx.Size(0, 24), style=wx.ALIGN_RIGHT)
 
         self.staticText3 = wx.StaticText(id=ID_ADDSLAVEDIALOGSTATICTEXT3,
-              label='EDS File:', name='staticText3', parent=self,
+              label=_('EDS File:'), name='staticText3', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(0, 17), style=0)
 
         self.EDSFile = wx.Choice(id=ID_ADDSLAVEDIALOGEDSFILE,
               name='EDSFile', parent=self, pos=wx.Point(0, 0),
               size=wx.Size(0, 24), style=0)
         
-        self.ImportEDS = wx.Button(id=ID_ADDSLAVEDIALOGIMPORTEDS, label='Import EDS',
+        self.ImportEDS = wx.Button(id=ID_ADDSLAVEDIALOGIMPORTEDS, label=_('Import EDS'),
               name='ImportEDS', parent=self, pos=wx.Point(0, 0),
               size=wx.Size(100, 32), style=0)
         self.ImportEDS.Bind(wx.EVT_BUTTON, self.OnImportEDSButton,
@@ -1197,21 +1195,21 @@
     def OnOK(self, event):
         error = []
         if self.SlaveName.GetValue() == "":
-            error.append("Slave Name")
+            error.append(_("Slave Name"))
         if self.SlaveNodeID.GetValue() == "":
-            error.append("Slave Node ID")
+            error.append(_("Slave Node ID"))
         if self.EDSFile.GetStringSelection() == "":
-            error.append("EDS File")
+            error.append(_("EDS File"))
         if len(error) > 0:
             text = ""
             for i, item in enumerate(error):
                 if i == 0:
                     text += item
                 elif i == len(error) - 1:
-                    text += " and %s"%item
+                    text += _(" and %s")%item
                 else:
-                    text += ", %s"%item 
-            message = wx.MessageDialog(self, "Form isn't complete. %s must be filled!"%text, "Error", wx.OK|wx.ICON_ERROR)
+                    text += _(", %s")%item 
+            message = wx.MessageDialog(self, _("Form isn't complete. %s must be filled!")%text, _("Error"), wx.OK|wx.ICON_ERROR)
             message.ShowModal()
             message.Destroy()
         else:
@@ -1222,16 +1220,16 @@
                 else:
                     nodeid = int(nodeid)
             except:
-                message = wx.MessageDialog(self, "Slave Node ID must be a value in decimal or hexadecimal!", "Error", wx.OK|wx.ICON_ERROR)
+                message = wx.MessageDialog(self, _("Slave Node ID must be a value in decimal or hexadecimal!"), _("Error"), wx.OK|wx.ICON_ERROR)
                 message.ShowModal()
                 message.Destroy()
                 return
             if not 0 <= nodeid <= 127:
-                message = wx.MessageDialog(self, "Slave Node ID must be between 0 and 127!", "Error", wx.OK|wx.ICON_ERROR)
+                message = wx.MessageDialog(self, _("Slave Node ID must be between 0 and 127!"), _("Error"), wx.OK|wx.ICON_ERROR)
                 message.ShowModal()
                 message.Destroy()
             elif nodeid == 0 or nodeid in self.NodeList.SlaveNodes.keys():
-                message = wx.MessageDialog(self, "A Node with this ID already exist in the network!", "Error", wx.OK|wx.ICON_ERROR)
+                message = wx.MessageDialog(self, _("A Node with this ID already exist in the network!"), _("Error"), wx.OK|wx.ICON_ERROR)
                 message.ShowModal()
                 message.Destroy()
             else:
@@ -1239,17 +1237,17 @@
 
     def OnImportEDSButton(self, event):
         dialog = wx.FileDialog(self,
-                               "Choose an EDS file",
+                               _("Choose an EDS file"),
                                os.getcwd(),
                                "",
-                               "EDS files (*.eds)|*.eds|All files|*.*",
+                               _("EDS files (*.eds)|*.eds|All files|*.*"),
                                wx.OPEN)
         if dialog.ShowModal() == wx.ID_OK:
             filepath = dialog.GetPath()
             if os.path.isfile(filepath):
                 result = self.NodeList.ImportEDSFile(filepath)
                 if result:
-                    message = wx.MessageDialog(self, "%s\nWould you like to replace it ?"%result, "Question", wx.YES_NO|wx.ICON_QUESTION)
+                    message = wx.MessageDialog(self, _("%s\nWould you like to replace it ?")%result, _("Question"), wx.YES_NO|wx.ICON_QUESTION)
                     if message.ShowModal() == wx.ID_YES:
                         self.NodeList.ImportEDSFile(filepath, True)
                     message.Destroy()
@@ -1284,6 +1282,10 @@
 #                            Editing DCF Entry Dialog
 #-------------------------------------------------------------------------------
 
+def DCFEntryTableColnames():
+    _ = lambda x : x
+    return [_("Index"), _("Subindex"), _("Size"), _("Value")]
+
 class DCFEntryValuesTable(wx.grid.PyGridTableBase):
     
     """
@@ -1296,7 +1298,7 @@
         self.colnames = colnames
         self.Parent = parent
         # XXX
-        # we need to store the row length and collength to
+        # we need to store the row length and col length to
         # see if the table has changed size
         self._rows = self.GetNumberRows()
         self._cols = self.GetNumberCols()
@@ -1307,27 +1309,29 @@
     def GetNumberRows(self):
         return len(self.data)
 
-    def GetColLabelValue(self, col):
+    def GetColLabelValue(self, col, translate=True):
         if col < len(self.colnames):
+            if translate:
+                return _(self.colnames[col])
             return self.colnames[col]
 
-    def GetRowLabelValues(self, row):
+    def GetRowLabelValues(self, row, translate=True):
         return row
 
     def GetValue(self, row, col):
         if row < self.GetNumberRows():
-            return str(self.data[row].get(self.GetColLabelValue(col), ""))
+            return str(self.data[row].get(self.GetColLabelValue(col, False), ""))
             
     def GetEditor(self, row, col):
         if row < self.GetNumberRows():
-            return self.editors[row].get(self.GetColLabelValue(col), "")
+            return self.editors[row].get(self.GetColLabelValue(col, False), "")
     
     def GetValueByName(self, row, colname):
         return self.data[row].get(colname)
 
     def SetValue(self, row, col, value):
         if col < len(self.colnames):
-            self.data[row][self.GetColLabelValue(col)] = value
+            self.data[row][self.GetColLabelValue(col, False)] = value
         
     def ResetView(self, grid):
         """
@@ -1437,11 +1441,11 @@
         wx.Dialog.__init__(self, id=ID_DCFENTRYVALUESDIALOG,
               name='DCFEntryValuesDialog', parent=prnt, pos=wx.Point(376, 223),
               size=wx.Size(400, 300), style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER,
-              title='Edit DCF Entry Values')
+              title=_('Edit DCF Entry Values'))
         self.SetClientSize(wx.Size(400, 300))
 
         self.staticText1 = wx.StaticText(id=ID_VARIABLEEDITORPANELSTATICTEXT1,
-              label='Entry Values:', name='staticText1', parent=self,
+              label=_('Entry Values:'), name='staticText1', parent=self,
               pos=wx.Point(0, 0), size=wx.Size(95, 17), style=0)
 
         self.ValuesGrid = wx.grid.Grid(id=ID_DCFENTRYVALUESDIALOGVALUESGRID,
@@ -1461,12 +1465,12 @@
             wx.grid.EVT_GRID_CELL_CHANGE(self.ValuesGrid, self.OnValuesGridCellChange)
             wx.grid.EVT_GRID_SELECT_CELL(self.ValuesGrid, self.OnValuesGridSelectCell)
         
-        self.AddButton = wx.Button(id=ID_DCFENTRYVALUESDIALOGADDBUTTON, label='Add',
+        self.AddButton = wx.Button(id=ID_DCFENTRYVALUESDIALOGADDBUTTON, label=_('Add'),
               name='AddButton', parent=self, pos=wx.Point(0, 0),
               size=wx.Size(72, 32), style=0)
         self.Bind(wx.EVT_BUTTON, self.OnAddButton, id=ID_DCFENTRYVALUESDIALOGADDBUTTON)
 
-        self.DeleteButton = wx.Button(id=ID_DCFENTRYVALUESDIALOGDELETEBUTTON, label='Delete',
+        self.DeleteButton = wx.Button(id=ID_DCFENTRYVALUESDIALOGDELETEBUTTON, label=_('Delete'),
               name='DeleteButton', parent=self, pos=wx.Point(0, 0),
               size=wx.Size(72, 32), style=0)
         self.Bind(wx.EVT_BUTTON, self.OnDeleteButton, id=ID_DCFENTRYVALUESDIALOGDELETEBUTTON)
@@ -1491,7 +1495,7 @@
         self.Values = []
         self.DefaultValue = {"Index" : 0, "Subindex" : 0, "Size" : 1, "Value" : 0}
         
-        self.Table = DCFEntryValuesTable(self, [], ["Index", "Subindex", "Size", "Value"])
+        self.Table = DCFEntryValuesTable(self, [], DCFEntryTableColnames())
         self.ValuesGrid.SetTable(self.Table)
         
     def OnValuesGridCellChange(self, event):
@@ -1501,7 +1505,7 @@
         try:
             self.Values[row][colname] = int(value, 16)
         except:
-            message = wx.MessageDialog(self, "\"%s\" is not a valid value!"%value, "Error", wx.OK|wx.ICON_ERROR)
+            message = wx.MessageDialog(self, _("\"%s\" is not a valid value!")%value, _("Error"), wx.OK|wx.ICON_ERROR)
             message.ShowModal()
             message.Destroy()
         wx.CallAfter(self.RefreshValues)
--- a/objdictgen/doc_index/DS301_index.py	Mon Jul 20 16:11:20 2009 +0200
+++ b/objdictgen/doc_index/DS301_index.py	Mon Jul 27 16:29:59 2009 +0200
@@ -24,8 +24,8 @@
 
 def OpenPDFDocIndex(index, cwd):
     if not os.path.isfile(os.path.join(cwd, "doc","301_v04000201.pdf")):
-        return """No documentation file available.
-Please read can festival documentation to know how to obtain one."""
+        return _("""No documentation file available.
+Please read can festival documentation to know how to obtain one.""")
     try:
         if index in DS301_PDF_INDEX:
             if wx.Platform == '__WXMSW__':
@@ -46,7 +46,7 @@
         return True
     except:
         if wx.Platform == '__WXMSW__':
-            return """Check if Acrobat Reader is correctly installed on your computer"""
+            return _("Check if Acrobat Reader is correctly installed on your computer")
         else:
-            return """Check if xpdf is correctly installed on your computer"""
+            return _("Check if xpdf is correctly installed on your computer")
         
\ No newline at end of file
--- a/objdictgen/eds_utils.py	Mon Jul 20 16:11:20 2009 +0200
+++ b/objdictgen/eds_utils.py	Mon Jul 27 16:29:59 2009 +0200
@@ -174,7 +174,7 @@
                             try:
                                 computed_value = int(value, 16)
                             except:
-                                raise SyntaxError, "\"%s\" is not a valid value for attribute \"%s\" of section \"[%s]\""%(value, keyname, section_name)
+                                raise SyntaxError, _("\"%s\" is not a valid value for attribute \"%s\" of section \"[%s]\"")%(value, keyname, section_name)
                         elif value.isdigit() or value.startswith("-") and value[1:].isdigit():
                             # Second case, value is a number and starts with "0" or "-0", then it's an octal value
                             if value.startswith("0") or value.startswith("-0"):
@@ -193,59 +193,59 @@
                         
                         if keyname.upper() == "NETNAME":
                             if not is_string(computed_value):
-                                raise SyntaxError, "Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\""%(value, keyname, section_name)
+                                raise SyntaxError, _("Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\"")%(value, keyname, section_name)
                             topology["Name"] = computed_value
                         elif keyname.upper() == "NODES":
                             if not is_integer(computed_value):
-                                raise SyntaxError, "Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\""%(value, keyname, section_name)
+                                raise SyntaxError, _("Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\"")%(value, keyname, section_name)
                             topology["Number"] = computed_value
                         elif keyname.upper() == "EDSBASENAME":
                             if not is_string(computed_value):
-                                raise SyntaxError, "Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\""%(value, keyname, section_name)
+                                raise SyntaxError, _("Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\"")%(value, keyname, section_name)
                             topology["Path"] = computed_value
                         elif nodepresent_result:
                             if not is_boolean(computed_value):
-                                raise SyntaxError, "Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\""%(value, keyname, section_name)
+                                raise SyntaxError, _("Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\"")%(value, keyname, section_name)
                             nodeid = int(nodepresent_result.groups()[0])
                             if nodeid not in topology["Nodes"].keys():
                                 topology["Nodes"][nodeid] = {}
                             topology["Nodes"][nodeid]["Present"] = computed_value
                         elif nodename_result:
                             if not is_string(value):
-                                raise SyntaxError, "Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\""%(value, keyname, section_name)
+                                raise SyntaxError, _("Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\"")%(value, keyname, section_name)
                             nodeid = int(nodename_result.groups()[0])
                             if nodeid not in topology["Nodes"].keys():
                                 topology["Nodes"][nodeid] = {}
                             topology["Nodes"][nodeid]["Name"] = computed_value
                         elif nodedcfname_result:
                             if not is_string(computed_value):
-                                raise SyntaxError, "Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\""%(value, keyname, section_name)
+                                raise SyntaxError, _("Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\"")%(value, keyname, section_name)
                             nodeid = int(nodedcfname_result.groups()[0])
                             if nodeid not in topology["Nodes"].keys():
                                 topology["Nodes"][nodeid] = {}
                             topology["Nodes"][nodeid]["DCFName"] = computed_value
                         else:
-                            raise SyntaxError, "Keyname \"%s\" not recognised for section \"[%s]\""%(keyname, section_name)
+                            raise SyntaxError, _("Keyname \"%s\" not recognised for section \"[%s]\"")%(keyname, section_name)
                         
                 # All lines that are not empty and are neither a comment neither not a valid assignment
                 elif assignment.strip() != "":
-                    raise SyntaxError, "\"%s\" is not a valid CPJ line"%assignment.strip()
+                    raise SyntaxError, _("\"%s\" is not a valid CPJ line")%assignment.strip()
         
             if "Number" not in topology.keys():
-                raise SyntaxError, "\"Nodes\" keyname in \"[%s]\" section is missing"%section_name
+                raise SyntaxError, _("\"Nodes\" keyname in \"[%s]\" section is missing")%section_name
         
             if topology["Number"] != len(topology["Nodes"]):
-                raise SyntaxError, "\"Nodes\" value not corresponding to number of nodes defined"
+                raise SyntaxError, _("\"Nodes\" value not corresponding to number of nodes defined")
             
             for nodeid, node in topology["Nodes"].items():
                 if "Present" not in node.keys():
-                    raise SyntaxError, "\"Node%dPresent\" keyname in \"[%s]\" section is missing"%(nodeid, section_name)
+                    raise SyntaxError, _("\"Node%dPresent\" keyname in \"[%s]\" section is missing")%(nodeid, section_name)
             
             networks.append(topology)
             
         # In other case, there is a syntax problem into CPJ file
         else:
-            raise SyntaxError, "Section \"[%s]\" is unrecognized"%section_name
+            raise SyntaxError, _("Section \"[%s]\" is unrecognized")%section_name
     
     return networks
 
@@ -275,7 +275,7 @@
             if section_name.upper() not in eds_dict:
                 eds_dict[section_name.upper()] = values
             else:
-                raise SyntaxError, "\"[%s]\" section is defined two times"%section_name
+                raise SyntaxError, _("\"[%s]\" section is defined two times")%section_name
         # Second case, section name is an index name 
         elif index_result:
             # Extract index number
@@ -288,7 +288,7 @@
                 values["subindexes"] = eds_dict[index]["subindexes"]
                 eds_dict[index] = values
             else:
-                raise SyntaxError, "\"[%s]\" section is defined two times"%section_name
+                raise SyntaxError, _("\"[%s]\" section is defined two times")%section_name
             is_entry = True
         # Third case, section name is a subindex name 
         elif subindex_result:
@@ -301,14 +301,14 @@
             if subindex not in eds_dict[index]["subindexes"]:
                 eds_dict[index]["subindexes"][subindex] = values
             else:
-                raise SyntaxError, "\"[%s]\" section is defined two times"%section_name
+                raise SyntaxError, _("\"[%s]\" section is defined two times")%section_name
             is_entry = True
         # Third case, section name is a subindex name 
         elif index_objectlinks_result:
             pass
         # In any other case, there is a syntax problem into EDS file
         else:
-            raise SyntaxError, "Section \"[%s]\" is unrecognized"%section_name
+            raise SyntaxError, _("Section \"[%s]\" is unrecognized")%section_name
         
         for assignment in assignments:
             # Escape any comment
@@ -330,13 +330,13 @@
                             test = int(value.upper().replace("$NODEID+", ""), 16)
                             computed_value = "\"%s\""%value
                         except:
-                            raise SyntaxError, "\"%s\" is not a valid formula for attribute \"%s\" of section \"[%s]\""%(value, keyname, section_name)
+                            raise SyntaxError, _("\"%s\" is not a valid formula for attribute \"%s\" of section \"[%s]\"")%(value, keyname, section_name)
                     # Second case, value starts with "0x", then it's an hexadecimal value
                     elif value.startswith("0x") or value.startswith("-0x"):
                         try:
                             computed_value = int(value, 16)
                         except:
-                            raise SyntaxError, "\"%s\" is not a valid value for attribute \"%s\" of section \"[%s]\""%(value, keyname, section_name)
+                            raise SyntaxError, _("\"%s\" is not a valid value for attribute \"%s\" of section \"[%s]\"")%(value, keyname, section_name)
                     elif value.isdigit() or value.startswith("-") and value[1:].isdigit():
                         # Third case, value is a number and starts with "0", then it's an octal value
                         if value.startswith("0") or value.startswith("-0"):
@@ -354,17 +354,17 @@
                         if is_entry:
                             # Verify that keyname is a possible attribute
                             if keyname.upper() not in ENTRY_ATTRIBUTES:
-                                raise SyntaxError, "Keyname \"%s\" not recognised for section \"[%s]\""%(keyname, section_name)
+                                raise SyntaxError, _("Keyname \"%s\" not recognised for section \"[%s]\"")%(keyname, section_name)
                             # Verify that value is valid
                             elif not ENTRY_ATTRIBUTES[keyname.upper()](computed_value):
-                                raise SyntaxError, "Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\""%(value, keyname, section_name)
+                                raise SyntaxError, _("Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\"")%(value, keyname, section_name)
                             else:
                                 values[keyname.upper()] = computed_value
                         else:
                             values[keyname.upper()] = computed_value
             # All lines that are not empty and are neither a comment neither not a valid assignment
             elif assignment.strip() != "":
-                raise SyntaxError, "\"%s\" is not a valid EDS line"%assignment.strip()
+                raise SyntaxError, _("\"%s\" is not a valid EDS line")%assignment.strip()
         
         # If entry is an index or a subindex
         if is_entry:
@@ -381,18 +381,18 @@
             if not keys.issuperset(required):
                 missing = required.difference(keys)._data.keys()
                 if len(missing) > 1:
-                    attributes = "Attributes %s are"%", ".join(["\"%s\""%attribute for attribute in missing])
+                    attributes = _("Attributes %s are")%_(", ").join(["\"%s\""%attribute for attribute in missing])
                 else:
-                    attributes = "Attribute \"%s\" is"%missing[0]
-                raise SyntaxError, "Error on section \"[%s]\":\n%s required for a%s entry"%(section_name, attributes, ENTRY_TYPES[values["OBJECTTYPE"]]["name"])
+                    attributes = _("Attribute \"%s\" is")%missing[0]
+                raise SyntaxError, _("Error on section \"[%s]\":\n%s required for a %s entry")%(section_name, attributes, ENTRY_TYPES[values["OBJECTTYPE"]]["name"])
             # Verify that parameters defined are all in the possible parameters
             if not keys.issubset(possible):
                 unsupported = keys.difference(possible)._data.keys()
                 if len(unsupported) > 1:
-                    attributes = "Attributes %s are"%", ".join(["\"%s\""%attribute for attribute in unsupported])
+                    attributes = _("Attributes %s are")%_(", ").join(["\"%s\""%attribute for attribute in unsupported])
                 else:
-                    attributes = "Attribute \"%s\" is"%unsupported[0]
-                raise SyntaxError, "Error on section \"[%s]\":\n%s unsupported for a%s entry"%(section_name, attributes, ENTRY_TYPES[values["OBJECTTYPE"]]["name"])
+                    attributes = _("Attribute \"%s\" is")%unsupported[0]
+                raise SyntaxError, _("Error on section \"[%s]\":\n%s unsupported for a %s entry")%(section_name, attributes, ENTRY_TYPES[values["OBJECTTYPE"]]["name"])
             
             VerifyValue(values, section_name, "ParameterValue")
             VerifyValue(values, section_name, "DefaultValue")
@@ -412,7 +412,7 @@
                 if not isinstance(values[param.upper()], (IntType, LongType)) and values[param.upper()].upper().find("$NODEID") == -1:
                     raise
         except:
-            raise SyntaxError, "Error on section \"[%s]\":\n%s incompatible with DataType"%(section_name, param)
+            raise SyntaxError, _("Error on section \"[%s]\":\n%s incompatible with DataType")%(section_name, param)
 
 
 # Function that write an EDS file after generate it's content
@@ -637,7 +637,7 @@
         WriteFile(filepath, content)
         return None
     except ValueError, message:
-        return "Unable to generate EDS file\n%s"%message
+        return _("Unable to generate EDS file\n%s")%message
     
 # Function that generate the CPJ file content for the nodelist
 def GenerateCPJContent(nodelist):
@@ -681,7 +681,7 @@
                 except:
                     pass
         # Read all entries in the EDS dictionary 
-        for entry, values in eds_dict.items():
+        for entry, values in eds_dict.iteritems():
             # All sections with a name in keynames are escaped
             if entry in SECTION_KEYNAMES:
                 pass
@@ -696,7 +696,7 @@
                         if values["OBJECTTYPE"] == 2:
                             values["DATATYPE"] = values.get("DATATYPE", 0xF)
                             if values["DATATYPE"] != 0xF:
-                                raise SyntaxError, "Domain entry 0x%4.4X DataType must be 0xF(DOMAIN) if defined"%entry
+                                raise SyntaxError, _("Domain entry 0x%4.4X DataType must be 0xF(DOMAIN) if defined")%entry
                         # Add mapping for entry
                         Node.AddMappingEntry(entry, name = values["PARAMETERNAME"], struct = 1)
                         # Add mapping for first subindex
@@ -774,10 +774,10 @@
                                 value = GetDefaultValue(Node, entry, subindex)
                             Node.AddEntry(entry, subindex, value)
                     else:
-                        raise SyntaxError, "Array or Record entry 0x%4.4X must have a \"SubNumber\" attribute"%entry
+                        raise SyntaxError, _("Array or Record entry 0x%4.4X must have a \"SubNumber\" attribute")%entry
         return Node
     except SyntaxError, message:
-        return "Unable to import EDS file\n%s"%message
+        return _("Unable to import EDS file\n%s")%message
 
 #-------------------------------------------------------------------------------
 #                             Main Function
--- a/objdictgen/gen_cfile.py	Mon Jul 20 16:11:20 2009 +0200
+++ b/objdictgen/gen_cfile.py	Mon Jul 27 16:29:59 2009 +0200
@@ -74,11 +74,11 @@
             elif values[0] == "BOOLEAN":
                 typeinfos = ("UNS8", None, "boolean", False)
             else:
-                raise ValueError, """!!! %s isn't a valid type for CanFestival."""%typename
+                raise ValueError, _("""!!! %s isn't a valid type for CanFestival.""")%typename
             if typeinfos[2] not in ["visible_string", "domain"]:
                 internal_types[typename] = typeinfos
         else:
-            raise ValueError, """!!! %s isn't a valid type for CanFestival."""%typename
+            raise ValueError, _("""!!! %s isn't a valid type for CanFestival.""")%typename
     return typeinfos
 
 def ComputeValue(type, value):
@@ -96,6 +96,12 @@
     cfile.write(content)
     cfile.close()
 
+def GetTypeName(Node, typenumber):
+    typename = Node.GetTypeName(typenumber)
+    if typename is None:
+        raise ValueError, _("""!!! Datatype with value "0x%4.4X" isn't defined in CanFestival.""")%typenumber
+    return typename
+
 def GenerateFileContent(Node, headerfilepath, pointers_dict = {}):
     """
     pointers_dict = {(Idx,Sidx):"VariableName",...}
@@ -186,11 +192,11 @@
         # Entry type is VAR
         if not isinstance(values, ListType):
             subentry_infos = Node.GetSubentryInfos(index, 0)
-            typename = Node.GetTypeName(subentry_infos["type"])
+            typename = GetTypeName(Node, subentry_infos["type"])
             typeinfos = GetValidTypeInfos(typename, [values])
             if typename is "DOMAIN" and index in variablelist:
                 if not typeinfos[1]:
-                    raise ValueError("\nDomain variable not initialized\nindex : 0x%04X\nsubindex 0x00"%index)
+                    raise ValueError, _("\nDomain variable not initialized\nindex : 0x%04X\nsubindex : 0x00")%index
             texts["subIndexType"] = typeinfos[0]
             if typeinfos[1] is not None:
                 texts["suffixe"] = "[%d]"%typeinfos[1]
@@ -206,7 +212,7 @@
             values = [values]
         else:
             subentry_infos = Node.GetSubentryInfos(index, 0)
-            typename = Node.GetTypeName(subentry_infos["type"])
+            typename = GetTypeName(Node, subentry_infos["type"])
             typeinfos = GetValidTypeInfos(typename)
             if index == 0x1003:
                 texts["value"] = 0
@@ -240,7 +246,7 @@
                                 sep = ""
                             value, comment = ComputeValue(typeinfos[2], value)
                             if len(value) is 2 and typename is "DOMAIN":
-                                raise ValueError("\nDomain variable not initialized\nindex : 0x%04X\nsubindex 0x%02X"%(index, subIndex))
+                                raise ValueError("\nDomain variable not initialized\nindex : 0x%04X\nsubindex : 0x%02X"%(index, subIndex))
                             mappedVariableContent += "    %s%s%s\n"%(value, sep, comment)
                     mappedVariableContent += "  };\n"
                 else:
@@ -261,7 +267,7 @@
                     texts["subIndex"] = subIndex
                     if subIndex > 0:
                         subentry_infos = Node.GetSubentryInfos(index, subIndex)
-                        typename = Node.GetTypeName(subentry_infos["type"])
+                        typename = GetTypeName(Node, subentry_infos["type"])
                         typeinfos = GetValidTypeInfos(typename, [values[subIndex]])
                         texts["subIndexType"] = typeinfos[0]
                         if typeinfos[1] is not None:
@@ -572,5 +578,5 @@
         WriteFile(headerfilepath, header)
         return None
     except ValueError, message:
-        return "Unable to Generate C File\n%s"%message
-
+        return _("Unable to Generate C File\n%s")%message
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/objdictgen/i18n/README	Mon Jul 27 16:29:59 2009 +0200
@@ -0,0 +1,8 @@
+To generate message.pot file:
+
+	python mki18n.py -p --domain=objdictgen
+	
+To generate .mo files for all languages:
+
+	python mki18n.py -m --moTarget=../locale --domain=objdictgen
+	
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/objdictgen/i18n/app.fil	Mon Jul 27 16:29:59 2009 +0200
@@ -0,0 +1,9 @@
+../commondialogs.py
+../eds_utils.py
+../gen_cfile.py
+../networkedit.py
+../nodelist.py
+../nodemanager.py
+../objdictedit.py
+../objdictgen.py
+../subindextable.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/objdictgen/i18n/messages.pot	Mon Jul 27 16:29:59 2009 +0200
@@ -0,0 +1,1024 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-27 15:15+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"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../networkedit.py:926
+msgid ""
+"\n"
+"An error happens.\n"
+"\n"
+"Click on OK for saving an error report.\n"
+"\n"
+"Please contact LOLITech at:\n"
+"+33 (0)3 29 57 60 42\n"
+"bugs_networkedit@lolitech.fr\n"
+"\n"
+"\n"
+"Error:\n"
+msgstr ""
+
+#: ../objdictedit.py:988
+msgid ""
+"\n"
+"An error happens.\n"
+"\n"
+"Click on OK for saving an error report.\n"
+"\n"
+"Please contact LOLITech at:\n"
+"+33 (0)3 29 57 60 42\n"
+"bugs_objdictedit@lolitech.fr\n"
+"\n"
+"\n"
+"Error:\n"
+msgstr ""
+
+#: ../gen_cfile.py:199
+#, python-format
+msgid ""
+"\n"
+"Domain variable not initialized\n"
+"index : 0x%04X\n"
+"subindex : 0x00"
+msgstr ""
+
+#: ../networkedit.py:34
+msgid ""
+"\n"
+"Usage of networkedit.py :"
+msgstr ""
+
+#: ../objdictedit.py:33
+msgid ""
+"\n"
+"Usage of objdictedit.py :"
+msgstr ""
+
+#: ../objdictgen.py:32
+msgid ""
+"\n"
+"Usage of objdictgen.py :"
+msgstr ""
+
+#: ../networkedit.py:938 ../objdictedit.py:1000
+msgid " : "
+msgstr ""
+
+#: ../commondialogs.py:560 ../commondialogs.py:1209
+#, python-format
+msgid " and %s"
+msgstr ""
+
+#: ../commondialogs.py:367 ../commondialogs.py:562
+msgid " must be integer!"
+msgstr ""
+
+#: ../commondialogs.py:365 ../commondialogs.py:560
+msgid " must be integers!"
+msgstr ""
+
+#: ../networkedit.py:640 ../objdictedit.py:546
+#, python-format
+msgid " possibly defined %d times"
+msgstr ""
+
+#: ../gen_cfile.py:77 ../gen_cfile.py:81
+#, python-format
+msgid "!!! %s isn't a valid type for CanFestival."
+msgstr ""
+
+#: ../gen_cfile.py:102
+#, python-format
+msgid "!!! Datatype with value \"0x%4.4X\" isn't defined in CanFestival."
+msgstr ""
+
+#: ../nodelist.py:158
+#, python-format
+msgid "\"%s\" EDS file is not available"
+msgstr ""
+
+#: ../nodelist.py:99
+#, python-format
+msgid "\"%s\" folder doesn't exist"
+msgstr ""
+
+#: ../eds_utils.py:232
+#, python-format
+msgid "\"%s\" is not a valid CPJ line"
+msgstr ""
+
+#: ../eds_utils.py:367
+#, python-format
+msgid "\"%s\" is not a valid EDS line"
+msgstr ""
+
+#: ../objdictedit.py:798
+#, python-format
+msgid "\"%s\" is not a valid file!"
+msgstr ""
+
+#: ../objdictedit.py:822 ../objdictedit.py:846
+#, python-format
+msgid "\"%s\" is not a valid folder!"
+msgstr ""
+
+#: ../eds_utils.py:333
+#, python-format
+msgid "\"%s\" is not a valid formula for attribute \"%s\" of section \"[%s]\""
+msgstr ""
+
+#: ../eds_utils.py:177 ../eds_utils.py:339
+#, python-format
+msgid "\"%s\" is not a valid value for attribute \"%s\" of section \"[%s]\""
+msgstr ""
+
+#: ../commondialogs.py:1508
+#, python-format
+msgid "\"%s\" is not a valid value!"
+msgstr ""
+
+#: ../eds_utils.py:242
+#, python-format
+msgid "\"Node%dPresent\" keyname in \"[%s]\" section is missing"
+msgstr ""
+
+#: ../eds_utils.py:235
+#, python-format
+msgid "\"Nodes\" keyname in \"[%s]\" section is missing"
+msgstr ""
+
+#: ../eds_utils.py:238
+msgid "\"Nodes\" value not corresponding to number of nodes defined"
+msgstr ""
+
+#: ../eds_utils.py:278 ../eds_utils.py:291 ../eds_utils.py:304
+#, python-format
+msgid "\"[%s]\" section is defined two times"
+msgstr ""
+
+#: ../commondialogs.py:1250
+#, python-format
+msgid ""
+"%s\n"
+"Would you like to replace it ?"
+msgstr ""
+
+#: ../networkedit.py:698 ../objdictedit.py:604
+#, python-format
+msgid "%s Profile"
+msgstr ""
+
+#: ../objdictgen.py:68
+#, python-format
+msgid "%s is not a valid file!"
+msgstr ""
+
+#: ../objdictedit.py:743
+#, python-format
+msgid "%s is not a valid folder!"
+msgstr ""
+
+#: ../networkedit.py:645 ../objdictedit.py:551
+#, python-format
+msgid "%s: %s entry of struct %s%s."
+msgstr ""
+
+#: ../eds_utils.py:384 ../eds_utils.py:392
+msgid ", "
+msgstr ""
+
+#: ../networkedit.py:914 ../networkedit.py:916 ../networkedit.py:917
+#: ../objdictedit.py:976 ../objdictedit.py:978 ../objdictedit.py:979
+msgid ",   "
+msgstr ""
+
+#: ../commondialogs.py:367 ../commondialogs.py:562 ../commondialogs.py:1211
+#, python-format
+msgid ", %s"
+msgstr ""
+
+#: ../networkedit.py:912 ../objdictedit.py:974
+msgid ". "
+msgstr ""
+
+#: ../commondialogs.py:1232
+msgid "A Node with this ID already exist in the network!"
+msgstr ""
+
+#: ../commondialogs.py:564
+msgid "A type must be selected!"
+msgstr ""
+
+#: ../networkedit.py:284 ../objdictedit.py:277
+msgid "About"
+msgstr ""
+
+#: ../networkedit.py:783 ../objdictedit.py:468
+msgid "About CAN Festival"
+msgstr ""
+
+#: ../commondialogs.py:1468 ../networkedit.py:185 ../objdictedit.py:175
+#: ../subindextable.py:456
+msgid "Add"
+msgstr ""
+
+#: ../commondialogs.py:275
+msgid "Add Map Variable"
+msgstr ""
+
+#: ../networkedit.py:209
+msgid "Add Slave Node"
+msgstr ""
+
+#: ../commondialogs.py:475
+msgid "Add User Type"
+msgstr ""
+
+#: ../commondialogs.py:1152
+msgid "Add a slave to nodelist"
+msgstr ""
+
+#: ../subindextable.py:338 ../subindextable.py:853
+msgid "Add subindexes"
+msgstr ""
+
+#: ../subindextable.py:346
+msgid "Add to DCF"
+msgstr ""
+
+#: ../objdictgen.py:75
+msgid "All done"
+msgstr ""
+
+#: ../subindextable.py:861 ../subindextable.py:882
+msgid "An integer is required!"
+msgstr ""
+
+#: ../eds_utils.py:777
+#, python-format
+msgid "Array or Record entry 0x%4.4X must have a \"SubNumber\" attribute"
+msgstr ""
+
+#: ../eds_utils.py:386 ../eds_utils.py:394
+#, python-format
+msgid "Attribute \"%s\" is"
+msgstr ""
+
+#: ../eds_utils.py:384 ../eds_utils.py:392
+#, python-format
+msgid "Attributes %s are"
+msgstr ""
+
+#: ../objdictedit.py:196
+msgid "Build Dictionary\tCTRL+B"
+msgstr ""
+
+#: ../networkedit.py:214
+msgid "Build Master Dictionary"
+msgstr ""
+
+#: ../networkedit.py:280 ../objdictedit.py:273
+msgid "CAN Festival Docs\tF2"
+msgstr ""
+
+#: ../objdictedit.py:829
+msgid "CANFestival C files (*.c)|*.c|All files|*.*"
+msgstr ""
+
+#: ../nodelist.py:303 ../nodelist.py:313
+msgid "Can't find node"
+msgstr ""
+
+#: ../objdictedit.py:455
+msgid "Check if Acrobat Reader is correctly installed on your computer"
+msgstr ""
+
+#: ../objdictedit.py:462
+msgid "Check if xpdf is correctly installed on your computer"
+msgstr ""
+
+#: ../commondialogs.py:1085 ../objdictedit.py:677 ../objdictedit.py:731
+#: ../objdictedit.py:776 ../objdictedit.py:805 ../objdictedit.py:829
+msgid "Choose a file"
+msgstr ""
+
+#: ../networkedit.py:455 ../networkedit.py:483
+msgid "Choose a project"
+msgstr ""
+
+#: ../networkedit.py:568
+msgid "Choose a slave to remove"
+msgstr ""
+
+#: ../commondialogs.py:1240
+msgid "Choose an EDS file"
+msgstr ""
+
+#: ../networkedit.py:194 ../objdictedit.py:184
+msgid "Close\tCTRL+W"
+msgstr ""
+
+#: ../objdictedit.py:491
+msgid "Close Application"
+msgstr ""
+
+#: ../objdictedit.py:752
+msgid "Close File"
+msgstr ""
+
+#: ../networkedit.py:521
+msgid "Close Project"
+msgstr ""
+
+#: ../nodemanager.py:220
+msgid "Couldn't find DS-302 in 'config' folder!"
+msgstr ""
+
+#: ../commondialogs.py:893
+msgid "Create a new Node"
+msgstr ""
+
+#: ../commondialogs.py:140
+msgid "Current Profile Indexes:"
+msgstr ""
+
+#: ../networkedit.py:232 ../objdictedit.py:225
+msgid "DS-301 Profile"
+msgstr ""
+
+#: ../networkedit.py:277 ../objdictedit.py:270
+msgid "DS-301 Standard\tF1"
+msgstr ""
+
+#: ../commondialogs.py:954 ../networkedit.py:234 ../objdictedit.py:227
+msgid "DS-302 Profile"
+msgstr ""
+
+#: ../commondialogs.py:718
+msgid "Default String Size:"
+msgstr ""
+
+#: ../subindextable.py:343
+msgid "Default value"
+msgstr ""
+
+#: ../commondialogs.py:1473 ../subindextable.py:363
+msgid "Delete"
+msgstr ""
+
+#: ../subindextable.py:340 ../subindextable.py:874
+msgid "Delete subindexes"
+msgstr ""
+
+#: ../commondialogs.py:726 ../commondialogs.py:982
+msgid "Description:"
+msgstr ""
+
+#: ../eds_utils.py:699
+#, python-format
+msgid "Domain entry 0x%4.4X DataType must be 0xF(DOMAIN) if defined"
+msgstr ""
+
+#: ../commondialogs.py:1202
+msgid "EDS File"
+msgstr ""
+
+#: ../commondialogs.py:1172
+msgid "EDS File:"
+msgstr ""
+
+#: ../nodelist.py:137
+msgid "EDS file already imported"
+msgstr ""
+
+#: ../commondialogs.py:1243 ../objdictedit.py:776 ../objdictedit.py:805
+msgid "EDS files (*.eds)|*.eds|All files|*.*"
+msgstr ""
+
+#: ../commondialogs.py:762 ../commondialogs.py:1038 ../networkedit.py:473
+#: ../networkedit.py:760 ../networkedit.py:766 ../objdictedit.py:436
+#: ../objdictedit.py:442 ../objdictedit.py:455 ../objdictedit.py:462
+#: ../objdictedit.py:665 ../subindextable.py:861 ../subindextable.py:882
+msgid "ERROR"
+msgstr ""
+
+#: ../networkedit.py:184 ../objdictedit.py:174
+msgid "Edit"
+msgstr ""
+
+#: ../networkedit.py:810 ../objdictedit.py:867
+#, python-format
+msgid "Edit %s Profile"
+msgstr ""
+
+#: ../commondialogs.py:112
+msgid "Edit Communication Profile"
+msgstr ""
+
+#: ../commondialogs.py:1444
+msgid "Edit DCF Entry Values"
+msgstr ""
+
+#: ../networkedit.py:801 ../objdictedit.py:858
+msgid "Edit DS-301 Profile"
+msgstr ""
+
+#: ../networkedit.py:806 ../objdictedit.py:863
+msgid "Edit DS-302 Profile"
+msgstr ""
+
+#: ../commondialogs.py:965
+msgid "Emergency support"
+msgstr ""
+
+#: ../commondialogs.py:1448
+msgid "Entry Values:"
+msgstr ""
+
+#: ../commondialogs.py:368 ../commondialogs.py:566 ../commondialogs.py:1212
+#: ../commondialogs.py:1223 ../commondialogs.py:1228 ../commondialogs.py:1232
+#: ../commondialogs.py:1508 ../networkedit.py:501 ../networkedit.py:513
+#: ../networkedit.py:527 ../networkedit.py:559 ../networkedit.py:583
+#: ../networkedit.py:875 ../networkedit.py:894 ../networkedit.py:939
+#: ../networkedit.py:949 ../objdictedit.py:696 ../objdictedit.py:721
+#: ../objdictedit.py:739 ../objdictedit.py:743 ../objdictedit.py:794
+#: ../objdictedit.py:798 ../objdictedit.py:818 ../objdictedit.py:822
+#: ../objdictedit.py:842 ../objdictedit.py:846 ../objdictedit.py:940
+#: ../objdictedit.py:959 ../objdictedit.py:1001 ../objdictedit.py:1011
+msgid "Error"
+msgstr ""
+
+#: ../eds_utils.py:415
+#, python-format
+msgid ""
+"Error on section \"[%s]\":\n"
+"%s incompatible with DataType"
+msgstr ""
+
+#: ../eds_utils.py:387
+#, python-format
+msgid ""
+"Error on section \"[%s]\":\n"
+"%s required for a %s entry"
+msgstr ""
+
+#: ../eds_utils.py:395
+#, python-format
+msgid ""
+"Error on section \"[%s]\":\n"
+"%s unsupported for a %s entry"
+msgstr ""
+
+#: ../networkedit.py:200 ../objdictedit.py:199
+msgid "Exit"
+msgstr ""
+
+#: ../objdictedit.py:814 ../objdictedit.py:838
+msgid "Export successful"
+msgstr ""
+
+#: ../objdictedit.py:194
+msgid "Export to EDS file"
+msgstr ""
+
+#: ../nodelist.py:188
+msgid "Fail to save Master Node"
+msgstr ""
+
+#: ../nodelist.py:228
+msgid "Fail to save node list"
+msgstr ""
+
+#: ../subindextable.py:46
+msgid "False"
+msgstr ""
+
+#: ../networkedit.py:182 ../objdictedit.py:173
+msgid "File"
+msgstr ""
+
+#: ../commondialogs.py:1212
+#, python-format
+msgid "Form isn't complete. %s must be filled!"
+msgstr ""
+
+#: ../commondialogs.py:368 ../commondialogs.py:566
+#, python-format
+msgid "Form isn't valid. %s"
+msgstr ""
+
+#: ../commondialogs.py:960
+msgid "Generate SYNC"
+msgstr ""
+
+#: ../subindextable.py:806
+#, python-format
+msgid "Give a new name for index 0x%04X"
+msgstr ""
+
+#: ../subindextable.py:443
+msgid "Have Callbacks"
+msgstr ""
+
+#: ../commondialogs.py:945
+msgid "Heartbeat"
+msgstr ""
+
+#: ../networkedit.py:186 ../objdictedit.py:176
+msgid "Help"
+msgstr ""
+
+#: ../commondialogs.py:1179
+msgid "Import EDS"
+msgstr ""
+
+#: ../objdictedit.py:192
+msgid "Import EDS file"
+msgstr ""
+
+#: ../objdictedit.py:790
+msgid "Import successful"
+msgstr ""
+
+#: ../commondialogs.py:353 ../commondialogs.py:1287
+msgid "Index"
+msgstr ""
+
+#: ../nodemanager.py:627
+#, python-format
+msgid "Index 0x%04X already defined!"
+msgstr ""
+
+#: ../nodemanager.py:629
+#, python-format
+msgid "Index 0x%04X isn't a valid index for Map Variable!"
+msgstr ""
+
+#: ../commondialogs.py:279
+msgid "Index:"
+msgstr ""
+
+#: ../networkedit.py:630 ../objdictedit.py:536
+#, python-format
+msgid "Index: 0x%04X"
+msgstr ""
+
+#: ../objdictedit.py:790 ../objdictedit.py:814 ../objdictedit.py:838
+msgid "Information"
+msgstr ""
+
+#: ../eds_utils.py:196 ../eds_utils.py:200 ../eds_utils.py:204
+#: ../eds_utils.py:208 ../eds_utils.py:215 ../eds_utils.py:222
+#: ../eds_utils.py:360
+#, python-format
+msgid "Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\""
+msgstr ""
+
+#: ../eds_utils.py:228 ../eds_utils.py:357
+#, python-format
+msgid "Keyname \"%s\" not recognised for section \"[%s]\""
+msgstr ""
+
+#: ../commondialogs.py:552
+msgid "Length"
+msgstr ""
+
+#: ../commondialogs.py:513
+msgid "Length:"
+msgstr ""
+
+#: ../networkedit.py:636 ../objdictedit.py:542
+msgid "Mandatory"
+msgstr ""
+
+#: ../networkedit.py:259 ../objdictedit.py:252 ../subindextable.py:65
+msgid "Map Variable"
+msgstr ""
+
+#: ../commondialogs.py:546
+msgid "Maximum"
+msgstr ""
+
+#: ../commondialogs.py:505
+msgid "Maximum:"
+msgstr ""
+
+#: ../commondialogs.py:541
+msgid "Minimum"
+msgstr ""
+
+#: ../commondialogs.py:497
+msgid "Minimum:"
+msgstr ""
+
+#: ../subindextable.py:361
+msgid "Modify"
+msgstr ""
+
+#: ../commondialogs.py:287 ../commondialogs.py:694 ../commondialogs.py:901
+msgid "Name:"
+msgstr ""
+
+#: ../networkedit.py:183
+msgid "Network"
+msgstr ""
+
+#: ../commondialogs.py:931
+msgid "Network Management:"
+msgstr ""
+
+#: ../networkedit.py:318 ../networkedit.py:596
+msgid "Networkedit"
+msgstr ""
+
+#: ../networkedit.py:594
+#, python-format
+msgid "Networkedit - %s"
+msgstr ""
+
+#: ../networkedit.py:190 ../objdictedit.py:180
+msgid "New\tCTRL+N"
+msgstr ""
+
+#: ../subindextable.py:52
+msgid "No"
+msgstr ""
+
+#: ../networkedit.py:880 ../objdictedit.py:945
+msgid "No map variable index left!"
+msgstr ""
+
+#: ../nodelist.py:235
+#, python-format
+msgid "Node 0x%2.2X doesn't exist"
+msgstr ""
+
+#: ../commondialogs.py:940
+msgid "Node Guarding"
+msgstr ""
+
+#: ../commondialogs.py:760 ../commondialogs.py:1036
+msgid "Node ID must be integer!"
+msgstr ""
+
+#: ../commondialogs.py:702 ../commondialogs.py:905
+msgid "Node ID:"
+msgstr ""
+
+#: ../commondialogs.py:690 ../networkedit.py:230 ../objdictedit.py:223
+msgid "Node infos"
+msgstr ""
+
+#: ../commondialogs.py:755 ../commondialogs.py:1031
+msgid "Node name can't be undefined or start with a digit and must be composed of alphanumerical characters or underscore!"
+msgstr ""
+
+#: ../nodelist.py:165
+#, python-format
+msgid "Node with \"0x%2.2X\" ID doesn't exist"
+msgstr ""
+
+#: ../commondialogs.py:935 ../commondialogs.py:1010 ../commondialogs.py:1020
+#: ../commondialogs.py:1056 ../commondialogs.py:1096
+msgid "None"
+msgstr ""
+
+#: ../commondialogs.py:358
+msgid "Number"
+msgstr ""
+
+#: ../subindextable.py:852
+msgid "Number of subindexes to add:"
+msgstr ""
+
+#: ../subindextable.py:873
+msgid "Number of subindexes to delete:"
+msgstr ""
+
+#: ../commondialogs.py:291
+msgid "Number:"
+msgstr ""
+
+#: ../commondialogs.py:1085
+msgid "OD Profile files (*.prf)|*.prf|All files|*.*"
+msgstr ""
+
+#: ../objdictedit.py:677 ../objdictedit.py:731
+msgid "OD files (*.od)|*.od|All files|*.*"
+msgstr ""
+
+#: ../objdictedit.py:309 ../objdictedit.py:517
+msgid "Objdictedit"
+msgstr ""
+
+#: ../objdictedit.py:515
+#, python-format
+msgid "Objdictedit - %s"
+msgstr ""
+
+#: ../networkedit.py:192 ../objdictedit.py:182
+msgid "Open\tCTRL+O"
+msgstr ""
+
+#: ../networkedit.py:634 ../objdictedit.py:540
+msgid "Optional"
+msgstr ""
+
+#: ../commondialogs.py:950
+msgid "Options:"
+msgstr ""
+
+#: ../commondialogs.py:1019 ../commondialogs.py:1084
+msgid "Other"
+msgstr ""
+
+#: ../networkedit.py:236 ../networkedit.py:706 ../objdictedit.py:229
+#: ../objdictedit.py:612
+msgid "Other Profile"
+msgstr ""
+
+#: ../networkedit.py:257 ../objdictedit.py:250 ../subindextable.py:63
+msgid "PDO Receive"
+msgstr ""
+
+#: ../networkedit.py:255 ../objdictedit.py:248 ../subindextable.py:64
+msgid "PDO Transmit"
+msgstr ""
+
+#: ../objdictgen.py:60
+msgid "Parsing input file"
+msgstr ""
+
+#: ../networkedit.py:154 ../objdictedit.py:145
+#, python-format
+msgid "Please point your browser at: %s"
+msgstr ""
+
+#: ../commondialogs.py:116
+msgid "Possible Profile Indexes:"
+msgstr ""
+
+#: ../nodemanager.py:218
+msgid "Problem with DS-302! Syntax Error."
+msgstr ""
+
+#: ../commondialogs.py:909
+msgid "Profile:"
+msgstr ""
+
+#: ../commondialogs.py:1250
+msgid "Question"
+msgstr ""
+
+#: ../subindextable.py:38 ../subindextable.py:39
+msgid "Read Only"
+msgstr ""
+
+#: ../subindextable.py:38 ../subindextable.py:39
+msgid "Read/Write"
+msgstr ""
+
+#: ../networkedit.py:227 ../objdictedit.py:220
+msgid "Redo\tCTRL+Y"
+msgstr ""
+
+#: ../networkedit.py:222 ../objdictedit.py:215
+msgid "Refresh\tCTRL+R"
+msgstr ""
+
+#: ../networkedit.py:211
+msgid "Remove Slave Node"
+msgstr ""
+
+#: ../networkedit.py:568
+msgid "Remove slave"
+msgstr ""
+
+#: ../subindextable.py:359
+msgid "Rename"
+msgstr ""
+
+#: ../subindextable.py:807
+msgid "Rename an index"
+msgstr ""
+
+#: ../networkedit.py:253 ../objdictedit.py:246 ../subindextable.py:62
+msgid "SDO Client"
+msgstr ""
+
+#: ../networkedit.py:251 ../objdictedit.py:244 ../subindextable.py:61
+msgid "SDO Server"
+msgstr ""
+
+#: ../networkedit.py:197 ../objdictedit.py:187
+msgid "Save\tCTRL+S"
+msgstr ""
+
+#: ../objdictedit.py:189
+msgid "Save As...\tALT+S"
+msgstr ""
+
+#: ../commondialogs.py:970
+msgid "Save Configuration"
+msgstr ""
+
+#: ../eds_utils.py:248 ../eds_utils.py:311
+#, python-format
+msgid "Section \"[%s]\" is unrecognized"
+msgstr ""
+
+#: ../commondialogs.py:1287
+msgid "Size"
+msgstr ""
+
+#: ../commondialogs.py:1198
+msgid "Slave Name"
+msgstr ""
+
+#: ../commondialogs.py:1156
+msgid "Slave Name:"
+msgstr ""
+
+#: ../commondialogs.py:1200
+msgid "Slave Node ID"
+msgstr ""
+
+#: ../commondialogs.py:1223
+msgid "Slave Node ID must be a value in decimal or hexadecimal!"
+msgstr ""
+
+#: ../commondialogs.py:1228
+msgid "Slave Node ID must be between 0 and 127!"
+msgstr ""
+
+#: ../commondialogs.py:1164
+msgid "Slave Node ID:"
+msgstr ""
+
+#: ../commondialogs.py:976
+msgid "Store EDS"
+msgstr ""
+
+#: ../commondialogs.py:1287
+msgid "Subindex"
+msgstr ""
+
+#: ../networkedit.py:631 ../objdictedit.py:537
+#, python-format
+msgid "Subindex: 0x%02X"
+msgstr ""
+
+#: ../nodemanager.py:264
+msgid ""
+"Syntax Error\n"
+"Bad OD Profile file!"
+msgstr ""
+
+#: ../networkedit.py:521 ../objdictedit.py:491 ../objdictedit.py:752
+msgid "There are changes, do you want to save?"
+msgstr ""
+
+#: ../nodemanager.py:659
+msgid "Too many User Types have already been defined!"
+msgstr ""
+
+#: ../subindextable.py:46
+msgid "True"
+msgstr ""
+
+#: ../commondialogs.py:283 ../commondialogs.py:479 ../commondialogs.py:710
+#: ../commondialogs.py:897
+msgid "Type:"
+msgstr ""
+
+#: ../gen_cfile.py:581
+#, python-format
+msgid ""
+"Unable to Generate C File\n"
+"%s"
+msgstr ""
+
+#: ../eds_utils.py:640
+#, python-format
+msgid ""
+"Unable to generate EDS file\n"
+"%s"
+msgstr ""
+
+#: ../eds_utils.py:780
+#, python-format
+msgid ""
+"Unable to import EDS file\n"
+"%s"
+msgstr ""
+
+#: ../nodelist.py:212
+#, python-format
+msgid ""
+"Unable to load CPJ file\n"
+"%s"
+msgstr ""
+
+#: ../nodemanager.py:288
+#, python-format
+msgid "Unable to load file \"%s\"!"
+msgstr ""
+
+#: ../commondialogs.py:321
+msgid "Undefined"
+msgstr ""
+
+#: ../networkedit.py:225 ../objdictedit.py:218
+msgid "Undo\tCTRL+Z"
+msgstr ""
+
+#: ../nodemanager.py:853
+#, python-format
+msgid "Unnamed%d"
+msgstr ""
+
+#: ../networkedit.py:261 ../objdictedit.py:254 ../subindextable.py:60
+msgid "User Type"
+msgstr ""
+
+#: ../commondialogs.py:1287
+msgid "Value"
+msgstr ""
+
+#: ../commondialogs.py:493
+msgid "Values"
+msgstr ""
+
+#: ../subindextable.py:38
+msgid "Write Only"
+msgstr ""
+
+#: ../objdictgen.py:70
+msgid "Writing output file"
+msgstr ""
+
+#: ../subindextable.py:52
+msgid "Yes"
+msgstr ""
+
+#: ../subindextable.py:82
+msgid "access"
+msgstr ""
+
+#: ../subindextable.py:82
+msgid "comment"
+msgstr ""
+
+#: ../networkedit.py:914 ../networkedit.py:916 ../objdictedit.py:976
+#: ../objdictedit.py:978
+msgid "file : "
+msgstr ""
+
+#: ../networkedit.py:917 ../objdictedit.py:979
+msgid "function : "
+msgstr ""
+
+#: ../networkedit.py:917 ../objdictedit.py:979
+msgid "line : "
+msgstr ""
+
+#: ../commondialogs.py:648
+msgid "master"
+msgstr ""
+
+#: ../subindextable.py:82
+msgid "name"
+msgstr ""
+
+#: ../subindextable.py:82
+msgid "save"
+msgstr ""
+
+#: ../commondialogs.py:648 ../commondialogs.py:1007
+msgid "slave"
+msgstr ""
+
+#: ../subindextable.py:82
+msgid "subindex"
+msgstr ""
+
+#: ../subindextable.py:82
+msgid "type"
+msgstr ""
+
+#: ../subindextable.py:82
+msgid "value"
+msgstr ""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/objdictgen/i18n/mki18n.py	Mon Jul 27 16:29:59 2009 +0200
@@ -0,0 +1,455 @@
+#! /usr/bin/env python
+# -*- coding: iso-8859-1 -*-
+# 
+#   PYTHON MODULE:     MKI18N.PY
+#                      =========
+# 
+#   Abstract:         Make Internationalization (i18n) files for an application.
+# 
+#   Copyright Pierre Rouleau. 2003. Released to public domain.
+# 
+#   Last update: Saturday, November 8, 2003. @ 15:55:18.
+# 
+#   File: ROUP2003N01::C:/dev/python/mki18n.py
+# 
+#   RCS $Header: //software/official/MKS/MKS_SI/TV_NT/dev/Python/rcs/mki18n.py 1.5 2003/11/05 19:40:04 PRouleau Exp $
+# 
+#   Update history:
+# 
+#   - File created: Saturday, June 7, 2003. by Pierre Rouleau
+#   - 10/06/03 rcs : RCS Revision 1.1  2003/06/10 10:06:12  PRouleau
+#   - 10/06/03 rcs : RCS Initial revision
+#   - 23/08/03 rcs : RCS Revision 1.2  2003/06/10 10:54:27  PRouleau
+#   - 23/08/03 P.R.: [code:fix] : The strings encoded in this file are encode in iso-8859-1 format.  Added the encoding
+#                    notification to Python to comply with Python's 2.3 PEP 263.
+#   - 23/08/03 P.R.: [feature:new] : Added the '-e' switch which is used to force the creation of the empty English .mo file.
+#   - 22/10/03 P.R.: [code] : incorporated utility functions in here to make script self sufficient.
+#   - 05/11/03 rcs : RCS Revision 1.4  2003/10/22 06:39:31  PRouleau
+#   - 05/11/03 P.R.: [code:fix] : included the unixpath() in this file.
+#   - 08/11/03 rcs : RCS Revision 1.5  2003/11/05 19:40:04  PRouleau
+# 
+#   RCS $Log: $
+# 
+# 
+# -----------------------------------------------------------------------------
+"""                                
+mki18n allows you to internationalize your software.  You can use it to 
+create the GNU .po files (Portable Object) and the compiled .mo files
+(Machine Object).
+
+mki18n module can be used from the command line or from within a script (see 
+the Usage at the end of this page).
+
+    Table of Contents
+    -----------------
+    
+    makePO()             -- Build the Portable Object file for the application --
+    catPO()              -- Concatenate one or several PO files with the application domain files. --
+    makeMO()             -- Compile the Portable Object files into the Machine Object stored in the right location. --
+    printUsage           -- Displays how to use this script from the command line --
+
+    Scriptexecution      -- Runs when invoked from the command line --
+
+
+NOTE:  this module uses GNU gettext utilities.
+
+You can get the gettext tools from the following sites:
+
+   - `GNU FTP site for gettetx`_ where several versions (0.10.40, 0.11.2, 0.11.5 and 0.12.1) are available.
+     Note  that you need to use `GNU libiconv`_ to use this. Get it from the `GNU
+     libiconv  ftp site`_ and get version 1.9.1 or later. Get the Windows .ZIP
+     files and install the packages inside c:/gnu. All binaries will be stored
+     inside  c:/gnu/bin.  Just  put c:/gnu/bin inside your PATH. You will need
+     the following files: 
+
+      - `gettext-runtime-0.12.1.bin.woe32.zip`_ 
+      - `gettext-tools-0.12.1.bin.woe32.zip`_
+      - `libiconv-1.9.1.bin.woe32.zip`_ 
+
+
+.. _GNU libiconv:                            http://www.gnu.org/software/libiconv/
+.. _GNU libiconv ftp site:                   http://www.ibiblio.org/pub/gnu/libiconv/
+.. _gettext-runtime-0.12.1.bin.woe32.zip:    ftp://ftp.gnu.org/gnu/gettext/gettext-runtime-0.12.1.bin.woe32.zip           
+.. _gettext-tools-0.12.1.bin.woe32.zip:      ftp://ftp.gnu.org/gnu/gettext/gettext-tools-0.12.1.bin.woe32.zip 
+.. _libiconv-1.9.1.bin.woe32.zip:            http://www.ibiblio.org/pub/gnu/libiconv/libiconv-1.9.1.bin.woe32.zip
+
+"""
+# -----------------------------------------------------------------------------
+# Module Import
+# -------------
+# 
+import os
+import sys
+import wx
+# -----------------------------------------------------------------------------
+# Global variables
+# ----------------
+#
+
+__author__ = "Pierre Rouleau"
+__version__= "$Revision: 1.5 $"
+
+# -----------------------------------------------------------------------------
+
+def getlanguageDict():
+    languageDict = {}
+    
+    for lang in [x for x in dir(wx) if x.startswith("LANGUAGE")]:
+        i = wx.Locale(wx.LANGUAGE_DEFAULT).GetLanguageInfo(getattr(wx, lang))
+        if i:
+            languageDict[i.CanonicalName] = i.Description
+
+    return languageDict
+
+# -----------------------------------------------------------------------------
+# m a k e P O ( )         -- Build the Portable Object file for the application --
+# ^^^^^^^^^^^^^^^
+#
+def makePO(applicationDirectoryPath,  applicationDomain=None, verbose=0) :
+    """Build the Portable Object Template file for the application.
+
+    makePO builds the .pot file for the application stored inside 
+    a specified directory by running xgettext for all application source 
+    files.  It finds the name of all files by looking for a file called 'app.fil'. 
+    If this file does not exists, makePo raises an IOError exception.
+    By default the application domain (the application
+    name) is the same as the directory name but it can be overridden by the
+    'applicationDomain' argument.
+
+    makePO always creates a new file called messages.pot.  If it finds files 
+    of the form app_xx.po where 'app' is the application name and 'xx' is one 
+    of the ISO 639 two-letter language codes, makePO resynchronizes those 
+    files with the latest extracted strings (now contained in messages.pot). 
+    This process updates all line location number in the language-specific
+    .po files and may also create new entries for translation (or comment out 
+    some).  The .po file is not changed, instead a new file is created with 
+    the .new extension appended to the name of the .po file.
+
+    By default the function does not display what it is doing.  Set the 
+    verbose argument to 1 to force it to print its commands.
+    """
+
+    if applicationDomain is None:
+        applicationName = fileBaseOf(applicationDirectoryPath,withPath=0)
+    else:
+        applicationName = applicationDomain
+    currentDir = os.getcwd()
+    os.chdir(applicationDirectoryPath)                    
+    if not os.path.exists('app.fil'):
+        raise IOError(2,'No module file: app.fil')
+
+    # Steps:                                  
+    #  Use xgettext to parse all application modules
+    #  The following switches are used:
+    #  
+    #   -s                          : sort output by string content (easier to use when we need to merge several .po files)
+    #   --files-from=app.fil        : The list of files is taken from the file: app.fil
+    #   --output=                   : specifies the name of the output file (using a .pot extension)
+    cmd = 'xgettext -s --no-wrap --language=Python --files-from=app.fil --output=messages.pot'
+    if verbose: print cmd
+    os.system(cmd)                                                
+
+    languageDict = getlanguageDict()
+
+    for langCode in languageDict.keys():
+        if langCode == 'en':
+            pass
+        else:
+            langPOfileName = "%s_%s.po" % (applicationName , langCode)
+            if os.path.exists(langPOfileName):
+                cmd = 'msgmerge -s --no-wrap "%s" messages.pot > "%s.new"' % (langPOfileName, langPOfileName)
+                if verbose: print cmd
+                os.system(cmd)
+    os.chdir(currentDir)
+
+# -----------------------------------------------------------------------------
+# c a t P O ( )         -- Concatenate one or several PO files with the application domain files. --
+# ^^^^^^^^^^^^^
+#
+def catPO(applicationDirectoryPath, listOf_extraPo, applicationDomain=None, targetDir=None, verbose=0) :
+    """Concatenate one or several PO files with the application domain files.
+    """
+
+    if applicationDomain is None:
+        applicationName = fileBaseOf(applicationDirectoryPath,withPath=0)
+    else:
+        applicationName = applicationDomain
+    currentDir = os.getcwd()
+    os.chdir(applicationDirectoryPath)
+
+    languageDict = getlanguageDict()
+
+    for langCode in languageDict.keys():
+        if langCode == 'en':
+            pass
+        else:
+            langPOfileName = "%s_%s.po" % (applicationName , langCode)
+            if os.path.exists(langPOfileName):
+                fileList = ''
+                for fileName in listOf_extraPo:
+                    fileList += ("%s_%s.po " % (fileName,langCode))
+                cmd = "msgcat -s --no-wrap %s %s > %s.cat" % (langPOfileName, fileList, langPOfileName)
+                if verbose: print cmd
+                os.system(cmd)
+                if targetDir is None:
+                    pass
+                else:
+                    mo_targetDir = "%s/%s/LC_MESSAGES" % (targetDir,langCode)
+                    cmd = "msgfmt --output-file=%s/%s.mo %s_%s.po.cat" % (mo_targetDir,applicationName,applicationName,langCode)
+                    if verbose: print cmd
+                    os.system(cmd)
+    os.chdir(currentDir)
+
+# -----------------------------------------------------------------------------
+# m a k e M O ( )         -- Compile the Portable Object files into the Machine Object stored in the right location. --
+# ^^^^^^^^^^^^^^^
+# 
+def makeMO(applicationDirectoryPath,targetDir='./locale',applicationDomain=None, verbose=0, forceEnglish=0) :
+    """Compile the Portable Object files into the Machine Object stored in the right location.
+
+    makeMO converts all translated language-specific PO files located inside 
+    the  application directory into the binary .MO files stored inside the 
+    LC_MESSAGES sub-directory for the found locale files.
+
+    makeMO searches for all files that have a name of the form 'app_xx.po' 
+    inside the application directory specified by the first argument.  The 
+    'app' is the application domain name (that can be specified by the 
+    applicationDomain argument or is taken from the directory name). The 'xx' 
+    corresponds to one of the ISO 639 two-letter language codes.
+
+    makeMo stores the resulting files inside a sub-directory of `targetDir`
+    called xx/LC_MESSAGES where 'xx' corresponds to the 2-letter language
+    code.
+    """
+    if targetDir is None:
+        targetDir = './locale'
+    if verbose:
+        print "Target directory for .mo files is: %s" % targetDir
+
+    if applicationDomain is None:
+        applicationName = fileBaseOf(applicationDirectoryPath,withPath=0)
+    else:
+        applicationName = applicationDomain
+    currentDir = os.getcwd()
+    os.chdir(applicationDirectoryPath)
+
+    languageDict = getlanguageDict()
+
+    for langCode in languageDict.keys():
+        if (langCode == 'en') and (forceEnglish==0):
+            pass
+        else:
+            langPOfileName = "%s_%s.po" % (applicationName , langCode)
+            if os.path.exists(langPOfileName):
+                mo_targetDir = "%s/%s/LC_MESSAGES" % (targetDir,langCode)
+                if not os.path.exists(mo_targetDir):
+                    mkdir(mo_targetDir)
+                cmd = 'msgfmt --output-file="%s/%s.mo" "%s_%s.po"' % (mo_targetDir,applicationName,applicationName,langCode)
+                if verbose: print cmd
+                os.system(cmd)
+    os.chdir(currentDir)
+   
+# -----------------------------------------------------------------------------
+# p r i n t U s a g e         -- Displays how to use this script from the command line --
+# ^^^^^^^^^^^^^^^^^^^
+#
+def printUsage(errorMsg=None) :
+    """Displays how to use this script from the command line."""
+    print """
+    ##################################################################################
+    #   mki18n :   Make internationalization files.                                  #
+    #              Uses the GNU gettext system to create PO (Portable Object) files  #
+    #              from source code, coimpile PO into MO (Machine Object) files.     #
+    #              Supports C,C++,Python source files.                               #
+    #                                                                                #
+    #   Usage: mki18n {OPTION} [appDirPath]                                          #
+    #                                                                                #
+    #   Options:                                                                     #
+    #     -e               : When -m is used, forces English .mo file creation       #
+    #     -h               : prints this help                                        #
+    #     -m               : make MO from existing PO files                          #
+    #     -p               : make PO, update PO files: Creates a new messages.pot    #
+    #                        file. Creates a dom_xx.po.new for every existing        #
+    #                        language specific .po file. ('xx' stands for the ISO639 #
+    #                        two-letter language code and 'dom' stands for the       #
+    #                        application domain name).  mki18n requires that you     #
+    #                        write a 'app.fil' file  which contains the list of all  #
+    #                        source code to parse.                                   #
+    #     -v               : verbose (prints comments while running)                 #
+    #     --domain=appName : specifies the application domain name.  By default      #
+    #                        the directory name is used.                             #
+    #     --moTarget=dir : specifies the directory where .mo files are stored.       #
+    #                      If not specified, the target is './locale'                #
+    #                                                                                #
+    #   You must specify one of the -p or -m option to perform the work.  You can    #
+    #   specify the path of the target application.  If you leave it out mki18n      #
+    #   will use the current directory as the application main directory.            #        
+    #                                                                                #
+    ##################################################################################"""
+    if errorMsg:
+        print "\n   ERROR: %s" % errorMsg
+
+# -----------------------------------------------------------------------------
+# f i l e B a s e O f ( )         -- Return base name of filename --
+# ^^^^^^^^^^^^^^^^^^^^^^^
+# 
+def fileBaseOf(filename,withPath=0) :
+   """fileBaseOf(filename,withPath) ---> string
+
+   Return base name of filename.  The returned string never includes the extension.
+   Use os.path.basename() to return the basename with the extension.  The 
+   second argument is optional.  If specified and if set to 'true' (non zero) 
+   the string returned contains the full path of the file name.  Otherwise the 
+   path is excluded.
+
+   [Example]
+   >>> fn = 'd:/dev/telepath/tvapp/code/test.html'
+   >>> fileBaseOf(fn)
+   'test'
+   >>> fileBaseOf(fn)
+   'test'
+   >>> fileBaseOf(fn,1)
+   'd:/dev/telepath/tvapp/code/test'
+   >>> fileBaseOf(fn,0)
+   'test'
+   >>> fn = 'abcdef'
+   >>> fileBaseOf(fn)
+   'abcdef'
+   >>> fileBaseOf(fn,1)
+   'abcdef'
+   >>> fn = "abcdef."
+   >>> fileBaseOf(fn)
+   'abcdef'
+   >>> fileBaseOf(fn,1)
+   'abcdef'
+   """            
+   pos = filename.rfind('.')             
+   if pos > 0:
+      filename = filename[:pos]
+   if withPath:
+      return filename
+   else:
+      return os.path.basename(filename)
+# -----------------------------------------------------------------------------
+# m k d i r ( )         -- Create a directory (and possibly the entire tree) --
+# ^^^^^^^^^^^^^
+# 
+def mkdir(directory) :
+   """Create a directory (and possibly the entire tree).
+
+   The os.mkdir() will fail to create a directory if one of the
+   directory in the specified path does not exist.  mkdir()
+   solves this problem.  It creates every intermediate directory
+   required to create the final path. Under Unix, the function 
+   only supports forward slash separator, but under Windows and MacOS
+   the function supports the forward slash and the OS separator (backslash
+   under windows).
+   """ 
+
+   # translate the path separators
+   directory = unixpath(directory)
+   # build a list of all directory elements
+   aList = filter(lambda x: len(x)>0, directory.split('/'))
+   theLen = len(aList)                     
+   # if the first element is a Windows-style disk drive
+   # concatenate it with the first directory
+   if aList[0].endswith(':'):
+      if theLen > 1:
+         aList[1] = aList[0] + '/' + aList[1]
+         del aList[0]      
+         theLen -= 1         
+   # if the original directory starts at root,
+   # make sure the first element of the list 
+   # starts at root too
+   if directory[0] == '/':     
+      aList[0] = '/' + aList[0]
+   # Now iterate through the list, check if the 
+   # directory exists and if not create it
+   theDir = ''
+   for i in range(theLen):
+      theDir += aList[i]
+      if not os.path.exists(theDir):
+         os.mkdir(theDir)
+      theDir += '/'   
+      
+# -----------------------------------------------------------------------------
+# u n i x p a t h ( )         -- Return a path name that contains Unix separator. --
+# ^^^^^^^^^^^^^^^^^^^
+# 
+def unixpath(thePath) :
+   r"""Return a path name that contains Unix separator.
+
+   [Example]
+   >>> unixpath(r"d:\test")
+   'd:/test'
+   >>> unixpath("d:/test/file.txt")
+   'd:/test/file.txt'
+   >>> 
+   """
+   thePath = os.path.normpath(thePath)
+   if os.sep == '/':
+      return thePath
+   else:
+      return thePath.replace(os.sep,'/')
+
+# ----------------------------------------------------------------------------- 
+
+# S c r i p t   e x e c u t i o n               -- Runs when invoked from the command line --
+# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+# 
+if __name__ == "__main__":
+    import getopt     # command line parsing
+    argc = len(sys.argv)
+    if argc == 1:
+        printUsage('Missing argument: specify at least one of -m or -p (or both).')
+        sys.exit(1)
+    # If there is some arguments, parse the command line
+    validOptions     = "ehmpv"
+    validLongOptions = ['domain=', 'moTarget=']             
+    option = {}
+    option['forceEnglish'] = 0
+    option['mo'] = 0
+    option['po'] = 0        
+    option['verbose'] = 0
+    option['domain'] = None
+    option['moTarget'] = None
+    try:
+        optionList,pargs = getopt.getopt(sys.argv[1:],validOptions,validLongOptions)
+    except getopt.GetoptError, e:
+        printUsage(e[0])
+        sys.exit(1)       
+    for (opt,val) in optionList:
+        if  (opt == '-h'):    
+            printUsage()
+            sys.exit(0) 
+        elif (opt == '-e'):         option['forceEnglish'] = 1
+        elif (opt == '-m'):         option['mo'] = 1
+        elif (opt == '-p'):         option['po'] = 1
+        elif (opt == '-v'):         option['verbose'] = 1
+        elif (opt == '--domain'):   option['domain'] = val
+        elif (opt == '--moTarget'): option['moTarget'] = val
+    if len(pargs) == 0:
+        appDirPath = os.getcwd()
+        if option['verbose']:
+            print "No project directory given. Using current one:  %s" % appDirPath
+    elif len(pargs) == 1:
+        appDirPath = pargs[0]
+    else:
+        printUsage('Too many arguments (%u).  Use double quotes if you have space in directory name' % len(pargs))
+        sys.exit(1)
+    if option['domain'] is None:
+        # If no domain specified, use the name of the target directory
+        option['domain'] = fileBaseOf(appDirPath)
+    if option['verbose']:
+        print "Application domain used is: '%s'" % option['domain']
+    if option['po']:
+        try:
+            makePO(appDirPath,option['domain'],option['verbose'])
+        except IOError, e:
+            printUsage(e[1] + '\n   You must write a file app.fil that contains the list of all files to parse.')
+    if option['mo']:
+        makeMO(appDirPath,option['moTarget'],option['domain'],option['verbose'],option['forceEnglish'])
+    sys.exit(1)            
+            
+
+# -----------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/objdictgen/i18n/objdictgen_fr_FR.po	Mon Jul 27 16:29:59 2009 +0200
@@ -0,0 +1,1232 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-27 15:15+0200\n"
+"PO-Revision-Date: 2009-07-27 15:17+0100\n"
+"Last-Translator: \n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../networkedit.py:926
+msgid ""
+"\n"
+"An error happens.\n"
+"\n"
+"Click on OK for saving an error report.\n"
+"\n"
+"Please contact LOLITech at:\n"
+"+33 (0)3 29 57 60 42\n"
+"bugs_networkedit@lolitech.fr\n"
+"\n"
+"\n"
+"Error:\n"
+msgstr ""
+"\n"
+"Une erreur est apparue.\n"
+"\n"
+"Appuyez sur 'Valider' pour enregistrer un rapport d'erreur.\n"
+"\n"
+"Veuillez contacter LOLITech au :\n"
+"+33 (0)3 29 57 60 42\n"
+"bugs_networkedit@lolitech.fr\n"
+"\n"
+"\n"
+"Erreur :\n"
+
+#: ../objdictedit.py:988
+msgid ""
+"\n"
+"An error happens.\n"
+"\n"
+"Click on OK for saving an error report.\n"
+"\n"
+"Please contact LOLITech at:\n"
+"+33 (0)3 29 57 60 42\n"
+"bugs_objdictedit@lolitech.fr\n"
+"\n"
+"\n"
+"Error:\n"
+msgstr ""
+"\n"
+"Une erreur est apparue.\n"
+"\n"
+"Appuyez sur 'Valider' pour enregistrer un rapport d'erreur.\n"
+"\n"
+"Veuillez contacter LOLITech au :\n"
+"+33 (0)3 29 57 60 42\n"
+"bugs_objdictedit@lolitech.fr\n"
+"\n"
+"\n"
+"Erreur:\n"
+
+#: ../gen_cfile.py:199
+#, python-format
+msgid ""
+"\n"
+"Domain variable not initialized\n"
+"index : 0x%04X\n"
+"subindex : 0x00"
+msgstr ""
+"\n"
+"La variable de type Domain n'est pas initialisée\n"
+"indice : 0x%04X\n"
+"sous-indice : 0x00"
+
+#: ../networkedit.py:34
+msgid ""
+"\n"
+"Usage of networkedit.py :"
+msgstr ""
+"\n"
+"Utilisation de networkedit.py :"
+
+#: ../objdictedit.py:33
+msgid ""
+"\n"
+"Usage of objdictedit.py :"
+msgstr ""
+"\n"
+"Utilisation de objdictedit.py :"
+
+#: ../objdictgen.py:32
+msgid ""
+"\n"
+"Usage of objdictgen.py :"
+msgstr ""
+"\n"
+"Utilisation de objdictgen.py :"
+
+#: ../networkedit.py:938
+#: ../objdictedit.py:1000
+msgid " : "
+msgstr " : "
+
+#: ../commondialogs.py:560
+#: ../commondialogs.py:1209
+#, python-format
+msgid " and %s"
+msgstr " et %s"
+
+#: ../commondialogs.py:367
+#: ../commondialogs.py:562
+msgid " must be integer!"
+msgstr " doit être un entier !"
+
+#: ../commondialogs.py:365
+#: ../commondialogs.py:560
+msgid " must be integers!"
+msgstr " doivent être des entiers !"
+
+#: ../networkedit.py:640
+#: ../objdictedit.py:546
+#, python-format
+msgid " possibly defined %d times"
+msgstr " peut être défini %s fois"
+
+#: ../gen_cfile.py:77
+#: ../gen_cfile.py:81
+#, python-format
+msgid "!!! %s isn't a valid type for CanFestival."
+msgstr "!!! %s n'est pas un type valide pour CanFestival."
+
+#: ../gen_cfile.py:102
+#, python-format
+msgid "!!! Datatype with value \"0x%4.4X\" isn't defined in CanFestival."
+msgstr "!!! Le type de donnée dont la valeur est \"0x%4.4X\" n'est pas défini dans CanFestival."
+
+#: ../nodelist.py:158
+#, python-format
+msgid "\"%s\" EDS file is not available"
+msgstr "Le fichier EDS \"%s\" n'est pas disponible"
+
+#: ../nodelist.py:99
+#, python-format
+msgid "\"%s\" folder doesn't exist"
+msgstr "Le répertoire \"%s\" n'existe pas"
+
+#: ../eds_utils.py:232
+#, python-format
+msgid "\"%s\" is not a valid CPJ line"
+msgstr "\"%s\" n'est pas une ligne de fichier CPJ valide"
+
+#: ../eds_utils.py:367
+#, python-format
+msgid "\"%s\" is not a valid EDS line"
+msgstr "\"%s\" n'est pas une ligne de fichier EDS valide"
+
+#: ../objdictedit.py:798
+#, python-format
+msgid "\"%s\" is not a valid file!"
+msgstr "\"%s\" n'est pas un fichier valide !"
+
+#: ../objdictedit.py:822
+#: ../objdictedit.py:846
+#, python-format
+msgid "\"%s\" is not a valid folder!"
+msgstr "\"%s\" n'est pas un répertoire valide !"
+
+#: ../eds_utils.py:333
+#, python-format
+msgid "\"%s\" is not a valid formula for attribute \"%s\" of section \"[%s]\""
+msgstr "\"%s\" n'est pas une formule valide pour l'attribut \"%s\" de la section \"[%s]\""
+
+#: ../eds_utils.py:177
+#: ../eds_utils.py:339
+#, python-format
+msgid "\"%s\" is not a valid value for attribute \"%s\" of section \"[%s]\""
+msgstr "\"%s\" n'est pas une valeur valide pour l'attribut \"%s\" de la section \"[%s]\""
+
+#: ../commondialogs.py:1508
+#, python-format
+msgid "\"%s\" is not a valid value!"
+msgstr "\"%s\" n'est pas une valeur valide !"
+
+#: ../eds_utils.py:242
+#, python-format
+msgid "\"Node%dPresent\" keyname in \"[%s]\" section is missing"
+msgstr "\"Node%dPresent\" mot clé est absent de la section \"[%s]\""
+
+#: ../eds_utils.py:235
+#, python-format
+msgid "\"Nodes\" keyname in \"[%s]\" section is missing"
+msgstr "\"Nodes\" mot clé est absent de la section \"[%s]\""
+
+#: ../eds_utils.py:238
+msgid "\"Nodes\" value not corresponding to number of nodes defined"
+msgstr "La valeur de \"Nodes\" ne correspond pas au nombre de noeuds définis"
+
+#: ../eds_utils.py:278
+#: ../eds_utils.py:291
+#: ../eds_utils.py:304
+#, python-format
+msgid "\"[%s]\" section is defined two times"
+msgstr "La section \"[%s]\" est définie deux fois"
+
+#: ../commondialogs.py:1250
+#, python-format
+msgid ""
+"%s\n"
+"Would you like to replace it ?"
+msgstr ""
+"%s\n"
+"Voulez-vous le remplacer ?"
+
+#: ../networkedit.py:698
+#: ../objdictedit.py:604
+#, python-format
+msgid "%s Profile"
+msgstr "Profil %s"
+
+#: ../objdictgen.py:68
+#, python-format
+msgid "%s is not a valid file!"
+msgstr "%s n'est pas un fichier valide !"
+
+#: ../objdictedit.py:743
+#, python-format
+msgid "%s is not a valid folder!"
+msgstr "%s n'est pas un répertoir valide !"
+
+#: ../networkedit.py:645
+#: ../objdictedit.py:551
+#, python-format
+msgid "%s: %s entry of struct %s%s."
+msgstr "%s : entrée %s de type %s%s."
+
+#: ../eds_utils.py:384
+#: ../eds_utils.py:392
+msgid ", "
+msgstr ", "
+
+#: ../networkedit.py:914
+#: ../networkedit.py:916
+#: ../networkedit.py:917
+#: ../objdictedit.py:976
+#: ../objdictedit.py:978
+#: ../objdictedit.py:979
+msgid ",   "
+msgstr ",   "
+
+#: ../commondialogs.py:367
+#: ../commondialogs.py:562
+#: ../commondialogs.py:1211
+#, python-format
+msgid ", %s"
+msgstr ", %s"
+
+#: ../networkedit.py:912
+#: ../objdictedit.py:974
+msgid ". "
+msgstr ". "
+
+#: ../commondialogs.py:1232
+msgid "A Node with this ID already exist in the network!"
+msgstr "Un noeud avec cet ID existe déjà dans le réseau !"
+
+#: ../commondialogs.py:564
+msgid "A type must be selected!"
+msgstr "Un type doit être sélectionné !"
+
+#: ../networkedit.py:284
+#: ../objdictedit.py:277
+msgid "About"
+msgstr "A propos"
+
+#: ../networkedit.py:783
+#: ../objdictedit.py:468
+msgid "About CAN Festival"
+msgstr "A propos de CanFestival"
+
+#: ../commondialogs.py:1468
+#: ../networkedit.py:185
+#: ../objdictedit.py:175
+#: ../subindextable.py:456
+msgid "Add"
+msgstr "Ajouter"
+
+#: ../commondialogs.py:275
+msgid "Add Map Variable"
+msgstr "Ajouter une variable mappable"
+
+#: ../networkedit.py:209
+msgid "Add Slave Node"
+msgstr "Ajouter un noeud esclave"
+
+#: ../commondialogs.py:475
+msgid "Add User Type"
+msgstr "Ajouter un type utilisateur"
+
+#: ../commondialogs.py:1152
+msgid "Add a slave to nodelist"
+msgstr "Ajouter un esclave à la liste des noeuds"
+
+#: ../subindextable.py:338
+#: ../subindextable.py:853
+msgid "Add subindexes"
+msgstr "Ajouter des sous-indices"
+
+#: ../subindextable.py:346
+msgid "Add to DCF"
+msgstr "Ajouter à la DCF"
+
+#: ../objdictgen.py:75
+msgid "All done"
+msgstr "Terminé"
+
+#: ../subindextable.py:861
+#: ../subindextable.py:882
+msgid "An integer is required!"
+msgstr "Un entier est nécessaire !"
+
+#: ../eds_utils.py:777
+#, python-format
+msgid "Array or Record entry 0x%4.4X must have a \"SubNumber\" attribute"
+msgstr "L'entrée de type Array ou Record à l'indice 0x%4.4X doit avoir un attribut \"SubNumber\" attribute"
+
+#: ../eds_utils.py:386
+#: ../eds_utils.py:394
+#, python-format
+msgid "Attribute \"%s\" is"
+msgstr "L'attribut \"%s\" est"
+
+#: ../eds_utils.py:384
+#: ../eds_utils.py:392
+#, python-format
+msgid "Attributes %s are"
+msgstr "Les attributs %s sont"
+
+#: ../objdictedit.py:196
+msgid "Build Dictionary\tCTRL+B"
+msgstr "Généré le dictionnaire\tCTRL+B"
+
+#: ../networkedit.py:214
+msgid "Build Master Dictionary"
+msgstr "Généré le dictionnaire du maître"
+
+#: ../networkedit.py:280
+#: ../objdictedit.py:273
+msgid "CAN Festival Docs\tF2"
+msgstr "Documentation de CAN Festival\tF2"
+
+#: ../objdictedit.py:829
+msgid "CANFestival C files (*.c)|*.c|All files|*.*"
+msgstr "Fichiers C de CANFestival (*.c)|*.c|Tous les fichiers|*.*"
+
+#: ../nodelist.py:303
+#: ../nodelist.py:313
+msgid "Can't find node"
+msgstr "Impossible de trouver le noeud"
+
+#: ../objdictedit.py:455
+msgid "Check if Acrobat Reader is correctly installed on your computer"
+msgstr "Vérifiez si Acrobat Reader est correctement installé sur votre ordinateur"
+
+#: ../objdictedit.py:462
+msgid "Check if xpdf is correctly installed on your computer"
+msgstr "Vérifiez si xpdf est correctement installé sur votre ordinateur"
+
+#: ../commondialogs.py:1085
+#: ../objdictedit.py:677
+#: ../objdictedit.py:731
+#: ../objdictedit.py:776
+#: ../objdictedit.py:805
+#: ../objdictedit.py:829
+msgid "Choose a file"
+msgstr "Choisissez un fichier"
+
+#: ../networkedit.py:455
+#: ../networkedit.py:483
+msgid "Choose a project"
+msgstr "Choisissez un projet"
+
+#: ../networkedit.py:568
+msgid "Choose a slave to remove"
+msgstr "Choisissez un esclave à supprimer"
+
+#: ../commondialogs.py:1240
+msgid "Choose an EDS file"
+msgstr "Choisissez un fichier EDS"
+
+#: ../networkedit.py:194
+#: ../objdictedit.py:184
+msgid "Close\tCTRL+W"
+msgstr "Fermer\tCTRL+W"
+
+#: ../objdictedit.py:491
+msgid "Close Application"
+msgstr "Fermer l'application"
+
+#: ../objdictedit.py:752
+msgid "Close File"
+msgstr "Fermer le fichier"
+
+#: ../networkedit.py:521
+msgid "Close Project"
+msgstr "Fermer le projet"
+
+#: ../nodemanager.py:220
+msgid "Couldn't find DS-302 in 'config' folder!"
+msgstr "Impossible de trouver la DS-302 dans le répertoire 'config' !"
+
+#: ../commondialogs.py:893
+msgid "Create a new Node"
+msgstr "Créer un nouveau noeud"
+
+#: ../commondialogs.py:140
+msgid "Current Profile Indexes:"
+msgstr "Indices actuels du profil :"
+
+#: ../networkedit.py:232
+#: ../objdictedit.py:225
+msgid "DS-301 Profile"
+msgstr "Profil DS-301"
+
+#: ../networkedit.py:277
+#: ../objdictedit.py:270
+msgid "DS-301 Standard\tF1"
+msgstr "Standard DS-301\tF1"
+
+#: ../commondialogs.py:954
+#: ../networkedit.py:234
+#: ../objdictedit.py:227
+msgid "DS-302 Profile"
+msgstr "Profil DS-302"
+
+#: ../commondialogs.py:718
+msgid "Default String Size:"
+msgstr "Taille des chaînes par défaut :"
+
+#: ../subindextable.py:343
+msgid "Default value"
+msgstr "Valeur par défaut"
+
+#: ../commondialogs.py:1473
+#: ../subindextable.py:363
+msgid "Delete"
+msgstr "Supprimer"
+
+#: ../subindextable.py:340
+#: ../subindextable.py:874
+msgid "Delete subindexes"
+msgstr "Supprimer les sous-indices"
+
+#: ../commondialogs.py:726
+#: ../commondialogs.py:982
+msgid "Description:"
+msgstr "Description :"
+
+#: ../eds_utils.py:699
+#, python-format
+msgid "Domain entry 0x%4.4X DataType must be 0xF(DOMAIN) if defined"
+msgstr "Le mot clé DataTytpe de l'entrée 0x%4.4X de type Domain doit avoir la valeur 0xF(DOMAIN) s'il est défini"
+
+#: ../commondialogs.py:1202
+msgid "EDS File"
+msgstr "Fichier EDS"
+
+#: ../commondialogs.py:1172
+msgid "EDS File:"
+msgstr "Fichier EDS :"
+
+#: ../nodelist.py:137
+msgid "EDS file already imported"
+msgstr "Le fichier EDS a déjà été importé"
+
+#: ../commondialogs.py:1243
+#: ../objdictedit.py:776
+#: ../objdictedit.py:805
+msgid "EDS files (*.eds)|*.eds|All files|*.*"
+msgstr "Fichiers EDS (*.eds)|*.eds|Tous les fichiers|*.*"
+
+#: ../commondialogs.py:762
+#: ../commondialogs.py:1038
+#: ../networkedit.py:473
+#: ../networkedit.py:760
+#: ../networkedit.py:766
+#: ../objdictedit.py:436
+#: ../objdictedit.py:442
+#: ../objdictedit.py:455
+#: ../objdictedit.py:462
+#: ../objdictedit.py:665
+#: ../subindextable.py:861
+#: ../subindextable.py:882
+msgid "ERROR"
+msgstr "ERREUR"
+
+#: ../networkedit.py:184
+#: ../objdictedit.py:174
+msgid "Edit"
+msgstr "Edition"
+
+#: ../networkedit.py:810
+#: ../objdictedit.py:867
+#, python-format
+msgid "Edit %s Profile"
+msgstr "Editer le profil %s"
+
+#: ../commondialogs.py:112
+msgid "Edit Communication Profile"
+msgstr "Editer le profile de communication"
+
+#: ../commondialogs.py:1444
+msgid "Edit DCF Entry Values"
+msgstr "Editer les valeurs de l'entrée de la DCF"
+
+#: ../networkedit.py:801
+#: ../objdictedit.py:858
+msgid "Edit DS-301 Profile"
+msgstr "Editer  le profil DS-301"
+
+#: ../networkedit.py:806
+#: ../objdictedit.py:863
+msgid "Edit DS-302 Profile"
+msgstr "Editer le profil DS-302"
+
+#: ../commondialogs.py:965
+msgid "Emergency support"
+msgstr "Support pour l'Emergency"
+
+#: ../commondialogs.py:1448
+msgid "Entry Values:"
+msgstr "Valeurs de l'entrée :"
+
+#: ../commondialogs.py:368
+#: ../commondialogs.py:566
+#: ../commondialogs.py:1212
+#: ../commondialogs.py:1223
+#: ../commondialogs.py:1228
+#: ../commondialogs.py:1232
+#: ../commondialogs.py:1508
+#: ../networkedit.py:501
+#: ../networkedit.py:513
+#: ../networkedit.py:527
+#: ../networkedit.py:559
+#: ../networkedit.py:583
+#: ../networkedit.py:875
+#: ../networkedit.py:894
+#: ../networkedit.py:939
+#: ../networkedit.py:949
+#: ../objdictedit.py:696
+#: ../objdictedit.py:721
+#: ../objdictedit.py:739
+#: ../objdictedit.py:743
+#: ../objdictedit.py:794
+#: ../objdictedit.py:798
+#: ../objdictedit.py:818
+#: ../objdictedit.py:822
+#: ../objdictedit.py:842
+#: ../objdictedit.py:846
+#: ../objdictedit.py:940
+#: ../objdictedit.py:959
+#: ../objdictedit.py:1001
+#: ../objdictedit.py:1011
+msgid "Error"
+msgstr "Erreur"
+
+#: ../eds_utils.py:415
+#, python-format
+msgid ""
+"Error on section \"[%s]\":\n"
+"%s incompatible with DataType"
+msgstr ""
+"Erreur dans la \"[%s]\" :\n"
+"%s est incompatible avec le type de donnée"
+
+#: ../eds_utils.py:387
+#, python-format
+msgid ""
+"Error on section \"[%s]\":\n"
+"%s required for a %s entry"
+msgstr ""
+"Erreur dans la \"[%s]\" :\n"
+"%s obligatoire pour une entrée %s"
+
+#: ../eds_utils.py:395
+#, python-format
+msgid ""
+"Error on section \"[%s]\":\n"
+"%s unsupported for a %s entry"
+msgstr ""
+"Erreur dans la \"[%s]\" :\n"
+"%s optionnel pour une entrée %s"
+
+#: ../networkedit.py:200
+#: ../objdictedit.py:199
+msgid "Exit"
+msgstr "Quitter"
+
+#: ../objdictedit.py:814
+#: ../objdictedit.py:838
+msgid "Export successful"
+msgstr "Exportation réussie"
+
+#: ../objdictedit.py:194
+msgid "Export to EDS file"
+msgstr "Exporter au format EDS"
+
+#: ../nodelist.py:188
+msgid "Fail to save Master Node"
+msgstr "L'enregistrement du noeud maître a échoué"
+
+#: ../nodelist.py:228
+msgid "Fail to save node list"
+msgstr "L'enregistrement de la liste des noeuds a échoué"
+
+#: ../subindextable.py:46
+msgid "False"
+msgstr "Faux"
+
+#: ../networkedit.py:182
+#: ../objdictedit.py:173
+msgid "File"
+msgstr "Fichier"
+
+#: ../commondialogs.py:1212
+#, python-format
+msgid "Form isn't complete. %s must be filled!"
+msgstr "Le formulaire n'est pas complet. %s doit être rempli !"
+
+#: ../commondialogs.py:368
+#: ../commondialogs.py:566
+#, python-format
+msgid "Form isn't valid. %s"
+msgstr "Le formulaire est incomplet. %s"
+
+#: ../commondialogs.py:960
+msgid "Generate SYNC"
+msgstr "Générer la synchro"
+
+#: ../subindextable.py:806
+#, python-format
+msgid "Give a new name for index 0x%04X"
+msgstr "Donnez un nouveau nom à l'indice 0x%04X"
+
+#: ../subindextable.py:443
+msgid "Have Callbacks"
+msgstr "Utilise des Callbacks"
+
+#: ../commondialogs.py:945
+msgid "Heartbeat"
+msgstr "Heartbeat"
+
+#: ../networkedit.py:186
+#: ../objdictedit.py:176
+msgid "Help"
+msgstr "Aide"
+
+#: ../commondialogs.py:1179
+msgid "Import EDS"
+msgstr "Importer un EDS"
+
+#: ../objdictedit.py:192
+msgid "Import EDS file"
+msgstr "Importer un fichier EDS"
+
+#: ../objdictedit.py:790
+msgid "Import successful"
+msgstr "L'importation a réussi"
+
+#: ../commondialogs.py:353
+#: ../commondialogs.py:1287
+msgid "Index"
+msgstr "Indice"
+
+#: ../nodemanager.py:627
+#, python-format
+msgid "Index 0x%04X already defined!"
+msgstr "L'indice 0x%04X est déjà défini !"
+
+#: ../nodemanager.py:629
+#, python-format
+msgid "Index 0x%04X isn't a valid index for Map Variable!"
+msgstr "L'indice 0x%04X n'est pas valide pour un variable mappable !"
+
+#: ../commondialogs.py:279
+msgid "Index:"
+msgstr "Indice :"
+
+#: ../networkedit.py:630
+#: ../objdictedit.py:536
+#, python-format
+msgid "Index: 0x%04X"
+msgstr "Indice: 0x%04X"
+
+#: ../objdictedit.py:790
+#: ../objdictedit.py:814
+#: ../objdictedit.py:838
+msgid "Information"
+msgstr "Information"
+
+#: ../eds_utils.py:196
+#: ../eds_utils.py:200
+#: ../eds_utils.py:204
+#: ../eds_utils.py:208
+#: ../eds_utils.py:215
+#: ../eds_utils.py:222
+#: ../eds_utils.py:360
+#, python-format
+msgid "Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\""
+msgstr "Valeur \"%s\" invalide pour le mot-clé \"%s\" dans la section \"[%s]\""
+
+#: ../eds_utils.py:228
+#: ../eds_utils.py:357
+#, python-format
+msgid "Keyname \"%s\" not recognised for section \"[%s]\""
+msgstr "Le mot-clé \"%s\" n'est pas reconnu dans la section \"[%s]\""
+
+#: ../commondialogs.py:552
+msgid "Length"
+msgstr "Taille"
+
+#: ../commondialogs.py:513
+msgid "Length:"
+msgstr "Taille:"
+
+#: ../networkedit.py:636
+#: ../objdictedit.py:542
+msgid "Mandatory"
+msgstr "Obligatoire"
+
+#: ../networkedit.py:259
+#: ../objdictedit.py:252
+#: ../subindextable.py:65
+msgid "Map Variable"
+msgstr "Variable mappable"
+
+#: ../commondialogs.py:546
+msgid "Maximum"
+msgstr "Maximum"
+
+#: ../commondialogs.py:505
+msgid "Maximum:"
+msgstr "Maximum :"
+
+#: ../commondialogs.py:541
+msgid "Minimum"
+msgstr "Minimum"
+
+#: ../commondialogs.py:497
+msgid "Minimum:"
+msgstr "Minimum :"
+
+#: ../subindextable.py:361
+msgid "Modify"
+msgstr "Modifier"
+
+#: ../commondialogs.py:287
+#: ../commondialogs.py:694
+#: ../commondialogs.py:901
+msgid "Name:"
+msgstr "Nom :"
+
+#: ../networkedit.py:183
+msgid "Network"
+msgstr "Réseau"
+
+#: ../commondialogs.py:931
+msgid "Network Management:"
+msgstr "Gestion de réseau :"
+
+#: ../networkedit.py:318
+#: ../networkedit.py:596
+msgid "Networkedit"
+msgstr "Networkedit"
+
+#: ../networkedit.py:594
+#, python-format
+msgid "Networkedit - %s"
+msgstr "Networkedit - %s"
+
+#: ../networkedit.py:190
+#: ../objdictedit.py:180
+msgid "New\tCTRL+N"
+msgstr "Nouveau\tCTRL+N"
+
+#: ../subindextable.py:52
+msgid "No"
+msgstr "Non"
+
+#: ../networkedit.py:880
+#: ../objdictedit.py:945
+msgid "No map variable index left!"
+msgstr "Il n'y a plus d'indice disponible pour une varaible mappable !"
+
+#: ../nodelist.py:235
+#, python-format
+msgid "Node 0x%2.2X doesn't exist"
+msgstr "Le noeud 0x%2.2X n'existe pas"
+
+#: ../commondialogs.py:940
+msgid "Node Guarding"
+msgstr "Node Guarding"
+
+#: ../commondialogs.py:760
+#: ../commondialogs.py:1036
+msgid "Node ID must be integer!"
+msgstr "L'ID du noeud doit être un entier !"
+
+#: ../commondialogs.py:702
+#: ../commondialogs.py:905
+msgid "Node ID:"
+msgstr "ID du noeud :"
+
+#: ../commondialogs.py:690
+#: ../networkedit.py:230
+#: ../objdictedit.py:223
+msgid "Node infos"
+msgstr "Propriétés du noeud"
+
+#: ../commondialogs.py:755
+#: ../commondialogs.py:1031
+msgid "Node name can't be undefined or start with a digit and must be composed of alphanumerical characters or underscore!"
+msgstr "Le nom d'un noeud ne peut être indéfini ou commencer par un chiffre et ne doit comporter que des caractères alphanumériaques ou des underscores !"
+
+#: ../nodelist.py:165
+#, python-format
+msgid "Node with \"0x%2.2X\" ID doesn't exist"
+msgstr "Le noeud d'ID \"0x%2.2X\" n'existe pas"
+
+#: ../commondialogs.py:935
+#: ../commondialogs.py:1010
+#: ../commondialogs.py:1020
+#: ../commondialogs.py:1056
+#: ../commondialogs.py:1096
+msgid "None"
+msgstr "Aucun"
+
+#: ../commondialogs.py:358
+msgid "Number"
+msgstr "Nombre"
+
+#: ../subindextable.py:852
+msgid "Number of subindexes to add:"
+msgstr "Nombre de sous-indices à ajouter :"
+
+#: ../subindextable.py:873
+msgid "Number of subindexes to delete:"
+msgstr "Nombre de sous-indices à supprimer :"
+
+#: ../commondialogs.py:291
+msgid "Number:"
+msgstr "Nombre :"
+
+#: ../commondialogs.py:1085
+msgid "OD Profile files (*.prf)|*.prf|All files|*.*"
+msgstr "Fichiers de profil d'OD (*.prf)|*.prf|Tous les fichiers|*.*"
+
+#: ../objdictedit.py:677
+#: ../objdictedit.py:731
+msgid "OD files (*.od)|*.od|All files|*.*"
+msgstr "Fichiers d'OD (*.od)|*.od|Tous les fichiers|*.*"
+
+#: ../objdictedit.py:309
+#: ../objdictedit.py:517
+msgid "Objdictedit"
+msgstr "Objdictedit"
+
+#: ../objdictedit.py:515
+#, python-format
+msgid "Objdictedit - %s"
+msgstr "Objdictedit - %s"
+
+#: ../networkedit.py:192
+#: ../objdictedit.py:182
+msgid "Open\tCTRL+O"
+msgstr "Ouvrir\tCTRL+O"
+
+#: ../networkedit.py:634
+#: ../objdictedit.py:540
+msgid "Optional"
+msgstr "Optionnel"
+
+#: ../commondialogs.py:950
+msgid "Options:"
+msgstr "Options :"
+
+#: ../commondialogs.py:1019
+#: ../commondialogs.py:1084
+msgid "Other"
+msgstr "Autre"
+
+#: ../networkedit.py:236
+#: ../networkedit.py:706
+#: ../objdictedit.py:229
+#: ../objdictedit.py:612
+msgid "Other Profile"
+msgstr "Autre profil"
+
+#: ../networkedit.py:257
+#: ../objdictedit.py:250
+#: ../subindextable.py:63
+msgid "PDO Receive"
+msgstr "PDO Reçu"
+
+#: ../networkedit.py:255
+#: ../objdictedit.py:248
+#: ../subindextable.py:64
+msgid "PDO Transmit"
+msgstr "PDO transmis"
+
+#: ../objdictgen.py:60
+msgid "Parsing input file"
+msgstr "Analyse du fichier d'entrée en cours"
+
+#: ../networkedit.py:154
+#: ../objdictedit.py:145
+#, python-format
+msgid "Please point your browser at: %s"
+msgstr "Veuillez afficher l'adresse suivante dans votre navigateur : %s"
+
+#: ../commondialogs.py:116
+msgid "Possible Profile Indexes:"
+msgstr "Indice possibles du profil :"
+
+#: ../nodemanager.py:218
+msgid "Problem with DS-302! Syntax Error."
+msgstr "Problème avec la DS-302 ! Erreur de syntaxe."
+
+#: ../commondialogs.py:909
+msgid "Profile:"
+msgstr "Profil :"
+
+#: ../commondialogs.py:1250
+msgid "Question"
+msgstr "Question"
+
+#: ../subindextable.py:38
+#: ../subindextable.py:39
+msgid "Read Only"
+msgstr "Lecture seule"
+
+#: ../subindextable.py:38
+#: ../subindextable.py:39
+msgid "Read/Write"
+msgstr "Lecture/Ecriture"
+
+#: ../networkedit.py:227
+#: ../objdictedit.py:220
+msgid "Redo\tCTRL+Y"
+msgstr "Refaire\tCTRL+Y"
+
+#: ../networkedit.py:222
+#: ../objdictedit.py:215
+msgid "Refresh\tCTRL+R"
+msgstr "Actualiser\tCTRL+R"
+
+#: ../networkedit.py:211
+msgid "Remove Slave Node"
+msgstr "Supprimer un noeud esclave"
+
+#: ../networkedit.py:568
+msgid "Remove slave"
+msgstr "Supprimer un esclave"
+
+#: ../subindextable.py:359
+msgid "Rename"
+msgstr "Renommer"
+
+#: ../subindextable.py:807
+msgid "Rename an index"
+msgstr "Renommer un indice"
+
+#: ../networkedit.py:253
+#: ../objdictedit.py:246
+#: ../subindextable.py:62
+msgid "SDO Client"
+msgstr "Client SDO"
+
+#: ../networkedit.py:251
+#: ../objdictedit.py:244
+#: ../subindextable.py:61
+msgid "SDO Server"
+msgstr "Serveur SDO"
+
+#: ../networkedit.py:197
+#: ../objdictedit.py:187
+msgid "Save\tCTRL+S"
+msgstr "Enregistrer\tCTRL+S"
+
+#: ../objdictedit.py:189
+msgid "Save As...\tALT+S"
+msgstr "Enregistrer sous...\tALT+S"
+
+#: ../commondialogs.py:970
+msgid "Save Configuration"
+msgstr "Enregistrer la configuration"
+
+#: ../eds_utils.py:248
+#: ../eds_utils.py:311
+#, python-format
+msgid "Section \"[%s]\" is unrecognized"
+msgstr "La section \"[%s]\" n'est pas reconnue"
+
+#: ../commondialogs.py:1287
+msgid "Size"
+msgstr "Taille"
+
+#: ../commondialogs.py:1198
+msgid "Slave Name"
+msgstr "Nom de l'exclave"
+
+#: ../commondialogs.py:1156
+msgid "Slave Name:"
+msgstr "Nom de l'esclave :"
+
+#: ../commondialogs.py:1200
+msgid "Slave Node ID"
+msgstr "ID du noeud esclave"
+
+#: ../commondialogs.py:1223
+msgid "Slave Node ID must be a value in decimal or hexadecimal!"
+msgstr "L'ID du noeud esclave doit être une valeur décimale ou héxadécimale !"
+
+#: ../commondialogs.py:1228
+msgid "Slave Node ID must be between 0 and 127!"
+msgstr "L'ID du noeud esclave doit être compris entre 0 et 127 !"
+
+#: ../commondialogs.py:1164
+msgid "Slave Node ID:"
+msgstr "ID du noeud esclave :"
+
+#: ../commondialogs.py:976
+msgid "Store EDS"
+msgstr "Stocker l'EDS"
+
+#: ../commondialogs.py:1287
+msgid "Subindex"
+msgstr "Sous-indice"
+
+#: ../networkedit.py:631
+#: ../objdictedit.py:537
+#, python-format
+msgid "Subindex: 0x%02X"
+msgstr "Sous-indice : 0x%02X"
+
+#: ../nodemanager.py:264
+msgid ""
+"Syntax Error\n"
+"Bad OD Profile file!"
+msgstr ""
+"Erreur de syntaxe\n"
+"Fichier de profil d'OD incorrect !"
+
+#: ../networkedit.py:521
+#: ../objdictedit.py:491
+#: ../objdictedit.py:752
+msgid "There are changes, do you want to save?"
+msgstr "Il y a des changements, voulez-vous enregistrer ?"
+
+#: ../nodemanager.py:659
+msgid "Too many User Types have already been defined!"
+msgstr "Trop de types utilisateurs ont déjà été définis !"
+
+#: ../subindextable.py:46
+msgid "True"
+msgstr "Vrai"
+
+#: ../commondialogs.py:283
+#: ../commondialogs.py:479
+#: ../commondialogs.py:710
+#: ../commondialogs.py:897
+msgid "Type:"
+msgstr "Type :"
+
+#: ../gen_cfile.py:581
+#, python-format
+msgid ""
+"Unable to Generate C File\n"
+"%s"
+msgstr ""
+"Impossible de générer le fichier C\n"
+"%s"
+
+#: ../eds_utils.py:640
+#, python-format
+msgid ""
+"Unable to generate EDS file\n"
+"%s"
+msgstr ""
+"Impossible de générer le fichier EDS\n"
+"%s"
+
+#: ../eds_utils.py:780
+#, python-format
+msgid ""
+"Unable to import EDS file\n"
+"%s"
+msgstr ""
+"Impossible d'importer le fichier EDS\n"
+"%s"
+
+#: ../nodelist.py:212
+#, python-format
+msgid ""
+"Unable to load CPJ file\n"
+"%s"
+msgstr ""
+"Impossible de charge le fichier CPJ\n"
+"%s"
+
+#: ../nodemanager.py:288
+#, python-format
+msgid "Unable to load file \"%s\"!"
+msgstr "Impossible de charger le fichier \"%s\" !"
+
+#: ../commondialogs.py:321
+msgid "Undefined"
+msgstr "Inconnu"
+
+#: ../networkedit.py:225
+#: ../objdictedit.py:218
+msgid "Undo\tCTRL+Z"
+msgstr "Défaire\tCTRL+Z"
+
+#: ../nodemanager.py:853
+#, python-format
+msgid "Unnamed%d"
+msgstr "Sansnom%d"
+
+#: ../networkedit.py:261
+#: ../objdictedit.py:254
+#: ../subindextable.py:60
+msgid "User Type"
+msgstr "Type utilisateur"
+
+#: ../commondialogs.py:1287
+msgid "Value"
+msgstr "Valeur"
+
+#: ../commondialogs.py:493
+msgid "Values"
+msgstr "Valeurs"
+
+#: ../subindextable.py:38
+msgid "Write Only"
+msgstr "Ecriture seule"
+
+#: ../objdictgen.py:70
+msgid "Writing output file"
+msgstr "Ecriture du fichier de sortie en cours"
+
+#: ../subindextable.py:52
+msgid "Yes"
+msgstr "Oui"
+
+#: ../subindextable.py:82
+msgid "access"
+msgstr "accès"
+
+#: ../subindextable.py:82
+msgid "comment"
+msgstr "commentaire"
+
+#: ../networkedit.py:914
+#: ../networkedit.py:916
+#: ../objdictedit.py:976
+#: ../objdictedit.py:978
+msgid "file : "
+msgstr "fichier :"
+
+#: ../networkedit.py:917
+#: ../objdictedit.py:979
+msgid "function : "
+msgstr "fonction :"
+
+#: ../networkedit.py:917
+#: ../objdictedit.py:979
+msgid "line : "
+msgstr "ligne :"
+
+#: ../commondialogs.py:648
+msgid "master"
+msgstr "maître"
+
+#: ../subindextable.py:82
+msgid "name"
+msgstr "nom"
+
+#: ../subindextable.py:82
+msgid "save"
+msgstr "enregistrer"
+
+#: ../commondialogs.py:648
+#: ../commondialogs.py:1007
+msgid "slave"
+msgstr "esclave"
+
+#: ../subindextable.py:82
+msgid "subindex"
+msgstr "sous-indice"
+
+#: ../subindextable.py:82
+msgid "type"
+msgstr "type"
+
+#: ../subindextable.py:82
+msgid "value"
+msgstr "valeur"
+
+#, fuzzy
+#~ msgid " must be integer !"
+#~ msgstr " doit être un entier !"
+
+#, fuzzy
+#~ msgid " must be integers !"
+#~ msgstr " doivent être des entiers !"
+#~ msgid " must be integer"
+#~ msgstr " doit être un entier"
+#~ msgid "s"
+#~ msgstr "s"
+#~ msgid "Node ID must be an integer!"
+#~ msgstr "L'ID du noeud doit être un entier !"
+#~ msgid "Node Infos"
+#~ msgstr "Propriétés du noeud"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/objdictgen/i18n/objdictgen_zh_CN.po	Mon Jul 27 16:29:59 2009 +0200
@@ -0,0 +1,1206 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-06-26 16:42+0200\n"
+"PO-Revision-Date: 2009-07-02 18:17+0100\n"
+"Last-Translator: \n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: networkedit.py:926
+msgid ""
+"\n"
+"An error happens.\n"
+"\n"
+"Click on OK for saving an error report.\n"
+"\n"
+"Please contact LOLITech at:\n"
+"+33 (0)3 29 57 60 42\n"
+"bugs_networkedit@lolitech.fr\n"
+"\n"
+"\n"
+"Error:\n"
+msgstr ""
+"\n"
+"一个错误发生了。\n"
+"\n"
+"点击确定以保存一个错误报告。\n"
+"\n"
+"请用以下方式联系LOLITech:\n"
+"+33 (0)3 29 57 60 42\n"
+"bugs_PLCOpenEditor@lolitech.fr\n"
+"\n"
+"\n"
+"错误:\n"
+
+#: objdictedit.py:979
+msgid ""
+"\n"
+"An error happens.\n"
+"\n"
+"Click on OK for saving an error report.\n"
+"\n"
+"Please contact LOLITech at:\n"
+"+33 (0)3 29 57 60 42\n"
+"bugs_objdictedit@lolitech.fr\n"
+"\n"
+"\n"
+"Error:\n"
+msgstr ""
+"\n"
+"一个错误发生了。\n"
+"\n"
+"点击确定以保存一个错误报告。\n"
+"\n"
+"请用以下方式联系LOLITech:\n"
+"+33 (0)3 29 57 60 42\n"
+"bugs_PLCOpenEditor@lolitech.fr\n"
+"\n"
+"\n"
+"错误:\n"
+
+#: gen_cfile.py:199
+#, python-format
+msgid ""
+"\n"
+"Domain variable not initialized\n"
+"index : 0x%04X\n"
+"subindex : 0x00"
+msgstr ""
+"\n"
+"域变量未初始化\n"
+"指标: 0x%04X\n"
+"子指标:: 0x00"
+
+#: networkedit.py:34
+msgid ""
+"\n"
+"Usage of networkedit.py :"
+msgstr ""
+"\n"
+"networkedit.py 的使用:"
+
+#: objdictedit.py:33
+msgid ""
+"\n"
+"Usage of objdictedit.py :"
+msgstr ""
+"\n"
+"objdictedit.py的使用:"
+
+#: objdictgen.py:30
+msgid ""
+"\n"
+"Usage of objdictgen.py :"
+msgstr ""
+"\n"
+"objdictgen.py的使用:"
+
+#: networkedit.py:938
+#: objdictedit.py:991
+msgid " : "
+msgstr ":"
+
+#: commondialogs.py:560
+#: commondialogs.py:1209
+#, python-format
+msgid " and %s"
+msgstr "和 %s"
+
+#: commondialogs.py:367
+#: commondialogs.py:562
+msgid " must be integer!"
+msgstr "必须为整数!"
+
+#: commondialogs.py:365
+#: commondialogs.py:560
+msgid " must be integers!"
+msgstr "必须为整数!"
+
+#: networkedit.py:640
+#: objdictedit.py:537
+#, python-format
+msgid " possibly defined %d times"
+msgstr " 可能定义 %d 时间"
+
+#: gen_cfile.py:77
+#: gen_cfile.py:81
+#, python-format
+msgid "!!! %s isn't a valid type for CanFestival."
+msgstr "!!! %s 不是一个CanFestival的有效类型。"
+
+#: gen_cfile.py:102
+#, python-format
+msgid "!!! Datatype with value \"0x%4.4X\" isn't defined in CanFestival."
+msgstr "!!! 带值的数据类型 \"0x%4.4X\" 在CanFestival中未定义。"
+
+#: nodelist.py:158
+#, python-format
+msgid "\"%s\" EDS file is not available"
+msgstr "\"%s\" EDS文件无效"
+
+#: nodelist.py:99
+#, python-format
+msgid "\"%s\" folder doesn't exist"
+msgstr "\"%s\" 文件夹不存在"
+
+#: eds_utils.py:232
+#, python-format
+msgid "\"%s\" is not a valid CPJ line"
+msgstr "\"%s\" 不是有效的 CPJ 线"
+
+#: eds_utils.py:367
+#, python-format
+msgid "\"%s\" is not a valid EDS line"
+msgstr "\"%s\" 不是有效的 EDS 线"
+
+#: objdictedit.py:789
+#, python-format
+msgid "\"%s\" is not a valid file!"
+msgstr "\"%s\" 不是有效的文件!"
+
+#: objdictedit.py:813
+#: objdictedit.py:837
+#, python-format
+msgid "\"%s\" is not a valid folder!"
+msgstr "\"%s\" 不是有效的文件夹!"
+
+#: eds_utils.py:333
+#, python-format
+msgid "\"%s\" is not a valid formula for attribute \"%s\" of section \"[%s]\""
+msgstr "\"%s\" 不是一个有效的公式用于属性 \"%s\" 段的 \"[%s]\""
+
+#: eds_utils.py:177
+#: eds_utils.py:339
+#, python-format
+msgid "\"%s\" is not a valid value for attribute \"%s\" of section \"[%s]\""
+msgstr "\"%s\" 不是一个有效的公式用于属性 \"%s\" 段的 \"[%s]\""
+
+#: commondialogs.py:1508
+#, python-format
+msgid "\"%s\" is not a valid value!"
+msgstr "\"%s\" 不是有效值!"
+
+#: eds_utils.py:242
+#, python-format
+msgid "\"Node%dPresent\" keyname in \"[%s]\" section is missing"
+msgstr "\"节点%d父目录\" 关键名在 \"[%s]\" 段消失"
+
+#: eds_utils.py:235
+#, python-format
+msgid "\"Nodes\" keyname in \"[%s]\" section is missing"
+msgstr "\"节点\" 关键名在 \"[%s]\" 段消失"
+
+#: eds_utils.py:238
+msgid "\"Nodes\" value not corresponding to number of nodes defined"
+msgstr "\"节点\" 值没有相应的被定义的一些节点"
+
+#: eds_utils.py:278
+#: eds_utils.py:291
+#: eds_utils.py:304
+#, python-format
+msgid "\"[%s]\" section is defined two times"
+msgstr "\"[%s]\" 段被定义两次"
+
+#: commondialogs.py:1250
+#, python-format
+msgid ""
+"%s\n"
+"Would you like to replace it ?"
+msgstr ""
+"%s\n"
+"你希望替换它吗?"
+
+#: networkedit.py:698
+#: objdictedit.py:595
+#, python-format
+msgid "%s Profile"
+msgstr "%s "
+
+#: objdictgen.py:66
+#, python-format
+msgid "%s is not a valid file!"
+msgstr "%s 不是有效的文件!"
+
+#: objdictedit.py:734
+#, python-format
+msgid "%s is not a valid folder!"
+msgstr "%s 不是有效的文件夹!"
+
+#: networkedit.py:645
+#: objdictedit.py:542
+#, python-format
+msgid "%s: %s entry of struct %s%s."
+msgstr "%s: %s 结构的入口 %s%s。"
+
+#: eds_utils.py:384
+#: eds_utils.py:392
+msgid ", "
+msgstr ","
+
+#: networkedit.py:914
+#: networkedit.py:916
+#: networkedit.py:917
+#: objdictedit.py:967
+#: objdictedit.py:969
+#: objdictedit.py:970
+msgid ",   "
+msgstr ","
+
+#: commondialogs.py:367
+#: commondialogs.py:562
+#: commondialogs.py:1211
+#, python-format
+msgid ", %s"
+msgstr ",%s"
+
+#: networkedit.py:912
+#: objdictedit.py:965
+msgid ". "
+msgstr "。"
+
+#: commondialogs.py:1232
+msgid "A Node with this ID already exist in the network!"
+msgstr "一个有ID的节点已存在于网络!"
+
+#: commondialogs.py:564
+msgid "A type must be selected!"
+msgstr "必须选择一个类型!"
+
+#: networkedit.py:284
+#: objdictedit.py:277
+msgid "About"
+msgstr "关于"
+
+#: networkedit.py:783
+#: objdictedit.py:459
+msgid "About CAN Festival"
+msgstr "关于 CAN Festival"
+
+#: commondialogs.py:1468
+#: networkedit.py:185
+#: objdictedit.py:175
+#: subindextable.py:456
+msgid "Add"
+msgstr "添加"
+
+#: commondialogs.py:275
+msgid "Add Map Variable"
+msgstr "添加地图变量"
+
+#: networkedit.py:209
+msgid "Add Slave Node"
+msgstr "添加从节点"
+
+#: commondialogs.py:475
+msgid "Add User Type"
+msgstr "添加用户类型"
+
+#: commondialogs.py:1152
+msgid "Add a slave to nodelist"
+msgstr "添加从到节点列表"
+
+#: subindextable.py:338
+#: subindextable.py:853
+msgid "Add subindexes"
+msgstr "添加子指标"
+
+#: subindextable.py:346
+msgid "Add to DCF"
+msgstr "添加至DCF"
+
+#: objdictgen.py:73
+msgid "All done"
+msgstr "全部完成"
+
+#: subindextable.py:861
+#: subindextable.py:882
+msgid "An integer is required!"
+msgstr "要求一个整数!"
+
+#: eds_utils.py:776
+#, python-format
+msgid "Array or Record entry 0x%4.4X must have a \"SubNumber\" attribute"
+msgstr "阵列或记录入口 0x%4.4X 必须有一个 \"子数\"属性"
+
+#: eds_utils.py:386
+#: eds_utils.py:394
+#, python-format
+msgid "Attribute \"%s\" is"
+msgstr "属性 \"%s\" 是"
+
+#: eds_utils.py:384
+#: eds_utils.py:392
+#, python-format
+msgid "Attributes %s are"
+msgstr "属性 %s 是"
+
+#: objdictedit.py:196
+msgid "Build Dictionary\tCTRL+B"
+msgstr "建立词典\tCTRL+B"
+
+#: networkedit.py:214
+msgid "Build Master Dictionary"
+msgstr "建立主词典"
+
+#: networkedit.py:280
+#: objdictedit.py:273
+msgid "CAN Festival Docs\tF2"
+msgstr "CAN Festival 文档\tF2"
+
+#: objdictedit.py:820
+msgid "CANFestival C files (*.c)|*.c|All files|*.*"
+msgstr "CANFestival C 文件 (*.c)|*.c|所有文件|*.*"
+
+#: nodelist.py:303
+#: nodelist.py:313
+msgid "Can't find node"
+msgstr "无法找到节点"
+
+#: commondialogs.py:1085
+#: objdictedit.py:668
+#: objdictedit.py:722
+#: objdictedit.py:767
+#: objdictedit.py:796
+#: objdictedit.py:820
+msgid "Choose a file"
+msgstr "选择一个文件"
+
+#: networkedit.py:455
+#: networkedit.py:483
+msgid "Choose a project"
+msgstr "选择一个项目"
+
+#: networkedit.py:568
+msgid "Choose a slave to remove"
+msgstr "选择一个从移除"
+
+#: commondialogs.py:1240
+msgid "Choose an EDS file"
+msgstr "选择一个EDS文件"
+
+#: networkedit.py:194
+#: objdictedit.py:184
+msgid "Close\tCTRL+W"
+msgstr "关闭\tCTRL+W"
+
+#: objdictedit.py:482
+msgid "Close Application"
+msgstr "关闭应用"
+
+#: objdictedit.py:743
+msgid "Close File"
+msgstr "关闭文件"
+
+#: networkedit.py:521
+msgid "Close Project"
+msgstr "关闭项目"
+
+#: nodemanager.py:220
+msgid "Couldn't find DS-302 in 'config' folder!"
+msgstr "不能在 “config” 文件夹中找到 DS-302 "
+
+#: commondialogs.py:893
+msgid "Create a new Node"
+msgstr "创建一个新节点"
+
+#: commondialogs.py:140
+msgid "Current Profile Indexes:"
+msgstr "当前Profile指标:"
+
+#: networkedit.py:232
+#: objdictedit.py:225
+msgid "DS-301 Profile"
+msgstr "DS-301 Profile"
+
+#: networkedit.py:277
+#: objdictedit.py:270
+msgid "DS-301 Standard\tF1"
+msgstr "DS-301 标准\tF1"
+
+#: commondialogs.py:954
+#: networkedit.py:234
+#: objdictedit.py:227
+msgid "DS-302 Profile"
+msgstr "DS-302 Profile"
+
+#: commondialogs.py:718
+msgid "Default String Size:"
+msgstr "默认字符串大小"
+
+#: subindextable.py:343
+msgid "Default value"
+msgstr "默认值"
+
+#: commondialogs.py:1473
+#: subindextable.py:363
+msgid "Delete"
+msgstr "删除"
+
+#: subindextable.py:340
+#: subindextable.py:874
+msgid "Delete subindexes"
+msgstr "删除子指标"
+
+#: commondialogs.py:726
+#: commondialogs.py:982
+msgid "Description:"
+msgstr "描述:"
+
+#: eds_utils.py:698
+#, python-format
+msgid "Domain entry 0x%4.4X DataType must be 0xF(DOMAIN) if defined"
+msgstr "域入口 0x%4.4X 数据类型必须是 0xF(DOMAIN) 如果已定义"
+
+#: commondialogs.py:1202
+msgid "EDS File"
+msgstr "EDS文件"
+
+#: commondialogs.py:1172
+msgid "EDS File:"
+msgstr "EDS文件:"
+
+#: nodelist.py:137
+msgid "EDS file already imported"
+msgstr "EDS文件已导入"
+
+#: commondialogs.py:1243
+#: objdictedit.py:767
+#: objdictedit.py:796
+msgid "EDS files (*.eds)|*.eds|All files|*.*"
+msgstr "EDS 文件 (*.eds)|*.eds|所有文件|*.*"
+
+#: commondialogs.py:762
+#: commondialogs.py:1038
+#: networkedit.py:473
+#: networkedit.py:760
+#: networkedit.py:766
+#: objdictedit.py:436
+#: objdictedit.py:442
+#: objdictedit.py:656
+#: subindextable.py:861
+#: subindextable.py:882
+msgid "ERROR"
+msgstr "错误"
+
+#: networkedit.py:184
+#: objdictedit.py:174
+msgid "Edit"
+msgstr "编辑"
+
+#: networkedit.py:810
+#: objdictedit.py:858
+#, python-format
+msgid "Edit %s Profile"
+msgstr "Edit %s Profile"
+
+#: commondialogs.py:112
+msgid "Edit Communication Profile"
+msgstr "编辑 Communication Profile"
+
+#: commondialogs.py:1444
+msgid "Edit DCF Entry Values"
+msgstr "编辑DCF输入值"
+
+#: networkedit.py:801
+#: objdictedit.py:849
+msgid "Edit DS-301 Profile"
+msgstr "编辑 DS-301 Profile"
+
+#: networkedit.py:806
+#: objdictedit.py:854
+msgid "Edit DS-302 Profile"
+msgstr "编辑 DS-302 Profile"
+
+#: commondialogs.py:965
+msgid "Emergency support"
+msgstr "紧急支援"
+
+#: commondialogs.py:1448
+msgid "Entry Values:"
+msgstr "输入值:"
+
+#: commondialogs.py:368
+#: commondialogs.py:566
+#: commondialogs.py:1212
+#: commondialogs.py:1223
+#: commondialogs.py:1228
+#: commondialogs.py:1232
+#: commondialogs.py:1508
+#: networkedit.py:501
+#: networkedit.py:513
+#: networkedit.py:527
+#: networkedit.py:559
+#: networkedit.py:583
+#: networkedit.py:875
+#: networkedit.py:894
+#: networkedit.py:939
+#: networkedit.py:949
+#: objdictedit.py:687
+#: objdictedit.py:712
+#: objdictedit.py:730
+#: objdictedit.py:734
+#: objdictedit.py:785
+#: objdictedit.py:789
+#: objdictedit.py:809
+#: objdictedit.py:813
+#: objdictedit.py:833
+#: objdictedit.py:837
+#: objdictedit.py:931
+#: objdictedit.py:950
+#: objdictedit.py:992
+#: objdictedit.py:1002
+msgid "Error"
+msgstr "错误"
+
+#: eds_utils.py:414
+#, python-format
+msgid ""
+"Error on section \"[%s]\":\n"
+"%s incompatible with DataType"
+msgstr ""
+"段有错误 \"[%s]\":\n"
+"%s 与数据类型不符合"
+
+#: eds_utils.py:387
+#, python-format
+msgid ""
+"Error on section \"[%s]\":\n"
+"%s required for a %s entry"
+msgstr ""
+"段有错误 \"[%s]\":\n"
+"%s 所需一个 %s 入口"
+
+#: eds_utils.py:395
+#, python-format
+msgid ""
+"Error on section \"[%s]\":\n"
+"%s unsupported for a %s entry"
+msgstr ""
+"段有错误 \"[%s]\":\n"
+"%s 不受支持 %s 入口"
+
+#: networkedit.py:200
+#: objdictedit.py:199
+msgid "Exit"
+msgstr "出口"
+
+#: objdictedit.py:805
+#: objdictedit.py:829
+msgid "Export successful"
+msgstr "导出成功"
+
+#: objdictedit.py:194
+msgid "Export to EDS file"
+msgstr "导出成EDS文件"
+
+#: nodelist.py:188
+msgid "Fail to save Master Node"
+msgstr "保存主节点失败"
+
+#: nodelist.py:228
+msgid "Fail to save node list"
+msgstr "保存节点列表失败"
+
+#: subindextable.py:46
+msgid "False"
+msgstr "假"
+
+#: networkedit.py:182
+#: objdictedit.py:173
+msgid "File"
+msgstr "文件"
+
+#: commondialogs.py:1212
+#, python-format
+msgid "Form isn't complete. %s must be filled!"
+msgstr "形式不完整。%s 必须补充!"
+
+#: commondialogs.py:368
+#: commondialogs.py:566
+#, python-format
+msgid "Form isn't valid. %s"
+msgstr "形式无效。%s"
+
+#: commondialogs.py:960
+msgid "Generate SYNC"
+msgstr "生成 SYNC"
+
+#: subindextable.py:806
+#, python-format
+msgid "Give a new name for index 0x%04X"
+msgstr "为指标重命名为 0x%04X"
+
+#: subindextable.py:443
+msgid "Have Callbacks"
+msgstr "有回访"
+
+#: commondialogs.py:945
+msgid "Heartbeat"
+msgstr "心跳"
+
+#: networkedit.py:186
+#: objdictedit.py:176
+msgid "Help"
+msgstr "帮助"
+
+#: commondialogs.py:1179
+msgid "Import EDS"
+msgstr "导入EDS"
+
+#: objdictedit.py:192
+msgid "Import EDS file"
+msgstr "导入EDS文件"
+
+#: objdictedit.py:781
+msgid "Import successful"
+msgstr "导入成功"
+
+#: commondialogs.py:353
+#: commondialogs.py:1287
+msgid "Index"
+msgstr "指标"
+
+#: nodemanager.py:627
+#, python-format
+msgid "Index 0x%04X already defined!"
+msgstr "指标 0x%04X 已定义!"
+
+#: nodemanager.py:629
+#, python-format
+msgid "Index 0x%04X isn't a valid index for Map Variable!"
+msgstr "指标 0x%04X 不是一个地图变量的有效指标!"
+
+#: commondialogs.py:279
+msgid "Index:"
+msgstr "指标:"
+
+#: networkedit.py:630
+#: objdictedit.py:527
+#, python-format
+msgid "Index: 0x%04X"
+msgstr "指标:0x%04X"
+
+#: objdictedit.py:781
+#: objdictedit.py:805
+#: objdictedit.py:829
+msgid "Information"
+msgstr "信息"
+
+#: eds_utils.py:196
+#: eds_utils.py:200
+#: eds_utils.py:204
+#: eds_utils.py:208
+#: eds_utils.py:215
+#: eds_utils.py:222
+#: eds_utils.py:360
+#, python-format
+msgid "Invalid value \"%s\" for keyname \"%s\" of section \"[%s]\""
+msgstr "无效值 \"%s\" 属于关键名 \"%s\" 段的 \"[%s]\""
+
+#: eds_utils.py:228
+#: eds_utils.py:357
+#, python-format
+msgid "Keyname \"%s\" not recognised for section \"[%s]\""
+msgstr "关键名 \"%s\" 不被段识别 \"[%s]\""
+
+#: commondialogs.py:552
+msgid "Length"
+msgstr "长度"
+
+#: commondialogs.py:513
+msgid "Length:"
+msgstr "长度:"
+
+#: networkedit.py:636
+#: objdictedit.py:533
+msgid "Mandatory"
+msgstr "强制"
+
+#: networkedit.py:259
+#: objdictedit.py:252
+#: subindextable.py:65
+msgid "Map Variable"
+msgstr "地图变量"
+
+#: commondialogs.py:546
+msgid "Maximum"
+msgstr "最大值"
+
+#: commondialogs.py:505
+msgid "Maximum:"
+msgstr "最大值:"
+
+#: commondialogs.py:541
+msgid "Minimum"
+msgstr "最小值"
+
+#: commondialogs.py:497
+msgid "Minimum:"
+msgstr "最小值:"
+
+#: subindextable.py:361
+msgid "Modify"
+msgstr "修改 "
+
+#: commondialogs.py:287
+#: commondialogs.py:694
+#: commondialogs.py:901
+msgid "Name:"
+msgstr "名字:"
+
+#: networkedit.py:183
+msgid "Network"
+msgstr "网络"
+
+#: commondialogs.py:931
+msgid "Network Management:"
+msgstr "网络管理:"
+
+#: networkedit.py:318
+#: networkedit.py:596
+msgid "Networkedit"
+msgstr "网络编辑器"
+
+#: networkedit.py:594
+#, python-format
+msgid "Networkedit - %s"
+msgstr "网络编辑器 - %s"
+
+#: networkedit.py:190
+#: objdictedit.py:180
+msgid "New\tCTRL+N"
+msgstr "新建\tCTRL+N"
+
+#: subindextable.py:52
+msgid "No"
+msgstr "否"
+
+#: networkedit.py:880
+#: objdictedit.py:936
+msgid "No map variable index left!"
+msgstr "无剩余地图变量指标!"
+
+#: nodelist.py:235
+#, python-format
+msgid "Node 0x%2.2X doesn't exist"
+msgstr "节点 0x%2.2X 不存在 "
+
+#: commondialogs.py:940
+msgid "Node Guarding"
+msgstr "节点护卫"
+
+#: commondialogs.py:760
+#: commondialogs.py:1036
+msgid "Node ID must be integer!"
+msgstr "节点ID必须是整数!"
+
+#: commondialogs.py:702
+#: commondialogs.py:905
+msgid "Node ID:"
+msgstr "节点ID:"
+
+#: commondialogs.py:690
+#: networkedit.py:230
+#: objdictedit.py:223
+msgid "Node infos"
+msgstr "节点信息"
+
+#: commondialogs.py:755
+#: commondialogs.py:1031
+msgid "Node name can't be undefined or start with a digit and must be composed of alphanumerical characters or underscore!"
+msgstr "节点名称不能是未定义的或以数字开头的,必须由字母数字混合字符或下划线组成!"
+
+#: nodelist.py:165
+#, python-format
+msgid "Node with \"0x%2.2X\" ID doesn't exist"
+msgstr "节点ID为 \"0x%2.2X\" 不存在"
+
+#: commondialogs.py:935
+#: commondialogs.py:1010
+#: commondialogs.py:1020
+#: commondialogs.py:1056
+#: commondialogs.py:1096
+msgid "None"
+msgstr "毫无"
+
+#: commondialogs.py:358
+msgid "Number"
+msgstr "数字"
+
+#: subindextable.py:852
+msgid "Number of subindexes to add:"
+msgstr "一些子指标需要添加:"
+
+#: subindextable.py:873
+msgid "Number of subindexes to delete:"
+msgstr "一些子指标需要删除:"
+
+#: commondialogs.py:291
+msgid "Number:"
+msgstr "数字:"
+
+#: commondialogs.py:1085
+msgid "OD Profile files (*.prf)|*.prf|All files|*.*"
+msgstr "OD Profile 文件 (*.prf)|*.prf|所有文件|*.*"
+
+#: objdictedit.py:668
+#: objdictedit.py:722
+msgid "OD files (*.od)|*.od|All files|*.*"
+msgstr "OD 文件 (*.od)|*.od|所有文件|*.*"
+
+#: objdictedit.py:309
+#: objdictedit.py:508
+msgid "Objdictedit"
+msgstr "Objdictedit"
+
+#: objdictedit.py:506
+#, python-format
+msgid "Objdictedit - %s"
+msgstr "Objdictedit - %s"
+
+#: networkedit.py:192
+#: objdictedit.py:182
+msgid "Open\tCTRL+O"
+msgstr "打开\tCTRL+O"
+
+#: networkedit.py:634
+#: objdictedit.py:531
+msgid "Optional"
+msgstr "可选择的"
+
+#: commondialogs.py:950
+msgid "Options:"
+msgstr "选项:"
+
+#: commondialogs.py:1019
+#: commondialogs.py:1084
+msgid "Other"
+msgstr "其他 "
+
+#: networkedit.py:236
+#: networkedit.py:706
+#: objdictedit.py:229
+#: objdictedit.py:603
+msgid "Other Profile"
+msgstr "其他 Profile"
+
+#: networkedit.py:257
+#: objdictedit.py:250
+#: subindextable.py:63
+msgid "PDO Receive"
+msgstr "PDO 接收"
+
+#: networkedit.py:255
+#: objdictedit.py:248
+#: subindextable.py:64
+msgid "PDO Transmit"
+msgstr "PDO传输"
+
+#: objdictgen.py:58
+msgid "Parsing input file"
+msgstr "解析输入文件"
+
+#: networkedit.py:154
+#: objdictedit.py:145
+#, python-format
+msgid "Please point your browser at: %s"
+msgstr "请在您的浏览器上输入下面的地址:%s "
+
+#: commondialogs.py:116
+msgid "Possible Profile Indexes:"
+msgstr "可能的 Profile 指标:"
+
+#: nodemanager.py:218
+msgid "Problem with DS-302! Syntax Error."
+msgstr "DS-302有问题!语法错误。"
+
+#: commondialogs.py:909
+msgid "Profile:"
+msgstr "Profile:"
+
+#: commondialogs.py:1250
+msgid "Question"
+msgstr "问题"
+
+#: subindextable.py:38
+#: subindextable.py:39
+msgid "Read Only"
+msgstr "只读"
+
+#: subindextable.py:38
+#: subindextable.py:39
+msgid "Read/Write"
+msgstr "读/写"
+
+#: networkedit.py:227
+#: objdictedit.py:220
+msgid "Redo\tCTRL+Y"
+msgstr "重做\tCTRL+Y"
+
+#: networkedit.py:222
+#: objdictedit.py:215
+msgid "Refresh\tCTRL+R"
+msgstr "刷新\tCTRL+R"
+
+#: networkedit.py:211
+msgid "Remove Slave Node"
+msgstr "移除从节点"
+
+#: networkedit.py:568
+msgid "Remove slave"
+msgstr "移除从"
+
+#: subindextable.py:359
+msgid "Rename"
+msgstr "重命名"
+
+#: subindextable.py:807
+msgid "Rename an index"
+msgstr "重命名一个指标"
+
+#: networkedit.py:253
+#: objdictedit.py:246
+#: subindextable.py:62
+msgid "SDO Client"
+msgstr "SDO 客户端"
+
+#: networkedit.py:251
+#: objdictedit.py:244
+#: subindextable.py:61
+msgid "SDO Server"
+msgstr "SDO 服务器"
+
+#: networkedit.py:197
+#: objdictedit.py:187
+msgid "Save\tCTRL+S"
+msgstr "保存\tCTRL+S"
+
+#: objdictedit.py:189
+msgid "Save As...\tALT+S"
+msgstr "另存为...\tALT+S"
+
+#: commondialogs.py:970
+msgid "Save Configuration"
+msgstr "保存配置"
+
+#: eds_utils.py:248
+#: eds_utils.py:311
+#, python-format
+msgid "Section \"[%s]\" is unrecognized"
+msgstr "段 \"[%s]\" 不能识别"
+
+#: commondialogs.py:1287
+msgid "Size"
+msgstr "尺寸"
+
+#: commondialogs.py:1198
+msgid "Slave Name"
+msgstr "从名字"
+
+#: commondialogs.py:1156
+msgid "Slave Name:"
+msgstr "从名字:"
+
+#: commondialogs.py:1200
+msgid "Slave Node ID"
+msgstr "从节点ID"
+
+#: commondialogs.py:1223
+msgid "Slave Node ID must be a value in decimal or hexadecimal!"
+msgstr "从节点ID必须是一个十进制或十六进制的值!"
+
+#: commondialogs.py:1228
+msgid "Slave Node ID must be between 0 and 127!"
+msgstr "从节点ID必须是0到127的数字!"
+
+#: commondialogs.py:1164
+msgid "Slave Node ID:"
+msgstr "从节点ID:"
+
+#: commondialogs.py:976
+msgid "Store EDS"
+msgstr "储存 EDS"
+
+#: commondialogs.py:1287
+msgid "Subindex"
+msgstr "子指标"
+
+#: networkedit.py:631
+#: objdictedit.py:528
+#, python-format
+msgid "Subindex: 0x%02X"
+msgstr "子指标: 0x%02X"
+
+#: nodemanager.py:264
+msgid ""
+"Syntax Error\n"
+"Bad OD Profile file!"
+msgstr ""
+"语法错误\n"
+"错的OD配置文件!"
+
+#: networkedit.py:521
+#: objdictedit.py:482
+#: objdictedit.py:743
+msgid "There are changes, do you want to save?"
+msgstr "有改动,你想保存吗?"
+
+#: nodemanager.py:659
+msgid "Too many User Types have already been defined!"
+msgstr "太多用户类型已被定义!"
+
+#: subindextable.py:46
+msgid "True"
+msgstr "真"
+
+#: commondialogs.py:283
+#: commondialogs.py:479
+#: commondialogs.py:710
+#: commondialogs.py:897
+msgid "Type:"
+msgstr "类型:"
+
+#: gen_cfile.py:581
+#, python-format
+msgid ""
+"Unable to Generate C File\n"
+"%s"
+msgstr ""
+"无法生成C文件\n"
+"%s"
+
+#: eds_utils.py:639
+#, python-format
+msgid ""
+"Unable to generate EDS file\n"
+"%s"
+msgstr ""
+"无法生成EDS文件\n"
+"%s"
+
+#: eds_utils.py:779
+#, python-format
+msgid ""
+"Unable to import EDS file\n"
+"%s"
+msgstr ""
+"无法导入EDS文件\n"
+"%s"
+
+#: nodelist.py:212
+#, python-format
+msgid ""
+"Unable to load CPJ file\n"
+"%s"
+msgstr ""
+"无法载入CPJ文件\n"
+"%s"
+
+#: nodemanager.py:288
+#, python-format
+msgid "Unable to load file \"%s\"!"
+msgstr "无法载入文件 \"%s\"!"
+
+#: commondialogs.py:321
+msgid "Undefined"
+msgstr "未定义"
+
+#: networkedit.py:225
+#: objdictedit.py:218
+msgid "Undo\tCTRL+Z"
+msgstr "撤消\tCTRL+Z"
+
+#: nodemanager.py:853
+#, python-format
+msgid "Unnamed%d"
+msgstr "未命名%d"
+
+#: networkedit.py:261
+#: objdictedit.py:254
+#: subindextable.py:60
+msgid "User Type"
+msgstr "用户类型"
+
+#: commondialogs.py:1287
+msgid "Value"
+msgstr "值"
+
+#: commondialogs.py:493
+msgid "Values"
+msgstr "值"
+
+#: subindextable.py:38
+msgid "Write Only"
+msgstr "只写"
+
+#: objdictgen.py:68
+msgid "Writing output file"
+msgstr "写输出文件"
+
+#: subindextable.py:52
+msgid "Yes"
+msgstr "是"
+
+#: subindextable.py:82
+msgid "access"
+msgstr "存取"
+
+#: subindextable.py:82
+msgid "comment"
+msgstr "注释"
+
+#: networkedit.py:914
+#: networkedit.py:916
+#: objdictedit.py:967
+#: objdictedit.py:969
+msgid "file : "
+msgstr "文件"
+
+#: networkedit.py:917
+#: objdictedit.py:970
+msgid "function : "
+msgstr "功能:"
+
+#: networkedit.py:917
+#: objdictedit.py:970
+msgid "line : "
+msgstr "线:"
+
+#: commondialogs.py:648
+msgid "master"
+msgstr "主控"
+
+#: subindextable.py:82
+msgid "name"
+msgstr "名字"
+
+#: subindextable.py:82
+msgid "save"
+msgstr "保存"
+
+#: commondialogs.py:648
+#: commondialogs.py:1007
+msgid "slave"
+msgstr "从"
+
+#: subindextable.py:82
+msgid "subindex"
+msgstr "子指标"
+
+#: subindextable.py:82
+msgid "type"
+msgstr "类型"
+
+#: subindextable.py:82
+msgid "value"
+msgstr "值"
+
Binary file objdictgen/locale/fr_FR/LC_MESSAGES/objdictgen.mo has changed
Binary file objdictgen/locale/zh_CN/LC_MESSAGES/objdictgen.mo has changed
--- a/objdictgen/networkedit.py	Mon Jul 20 16:11:20 2009 +0200
+++ b/objdictgen/networkedit.py	Mon Jul 27 16:29:59 2009 +0200
@@ -27,7 +27,60 @@
 from types import *
 import os, re, platform, sys, time, traceback, getopt
 
-__version__ = "$Revision$"
+__version__ = "$Revision: 1.27 $"
+
+if __name__ == '__main__':
+    def usage():
+        print _("\nUsage of networkedit.py :")
+        print "\n   %s [Projectpath]\n"%sys.argv[0]
+
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], "h", ["help"])
+    except getopt.GetoptError:
+        # print help information and exit:
+        usage()
+        sys.exit(2)
+
+    for o, a in opts:
+        if o in ("-h", "--help"):
+            usage()
+            sys.exit()
+
+    if len(args) == 0:
+        projectOpen = None 
+    elif len(args) == 1:
+        projectOpen = args[0]
+    else:
+        usage()
+        sys.exit(2)
+    
+    app = wx.PySimpleApp()
+
+ScriptDirectory = os.path.split(os.path.realpath(__file__))[0]
+
+# Import module for internationalization
+import gettext
+import __builtin__
+
+# Get folder containing translation files
+localedir = os.path.join(ScriptDirectory,"locale")
+# Get the default language
+langid = wx.LANGUAGE_DEFAULT
+# Define translation domain (name of translation files)
+domain = "objdictgen"
+
+# Define locale for wx
+loc = __builtin__.__dict__.get('loc', None)
+if loc is None:
+    loc = wx.Locale(langid)
+    __builtin__.__dict__['loc'] = loc
+# Define location for searching translation files
+loc.AddCatalogLookupPathPrefix(localedir)
+# Define locale domain
+loc.AddCatalog(domain)
+
+if __name__ == '__main__':
+    __builtin__.__dict__['_'] = wx.GetTranslation
 
 from nodelist import *
 from nodemanager import *
@@ -35,8 +88,6 @@
 from commondialogs import *
 from doc_index.DS301_index import *
 
-ScriptDirectory = os.path.split(os.path.realpath(__file__))[0]
-
 try:
     import wx.html
 
@@ -100,7 +151,7 @@
             try:
                 import webbrowser
             except ImportError:
-                wx.MessageBox('Please point your browser at: %s' % url)
+                wx.MessageBox(_('Please point your browser at: %s') % url)
             else:
                 webbrowser.open(url)
     
@@ -128,25 +179,25 @@
 class networkedit(wx.Frame):
     def _init_coll_MenuBar_Menus(self, parent):
         if self.ModeSolo:
-            parent.Append(menu=self.FileMenu, title='File')
-        parent.Append(menu=self.NetworkMenu, title='Network')
-        parent.Append(menu=self.EditMenu, title='Edit')
-        parent.Append(menu=self.AddMenu, title='Add')
-        parent.Append(menu=self.HelpMenu, title='Help')
+            parent.Append(menu=self.FileMenu, title=_('File'))
+        parent.Append(menu=self.NetworkMenu, title=_('Network'))
+        parent.Append(menu=self.EditMenu, title=_('Edit'))
+        parent.Append(menu=self.AddMenu, title=_('Add'))
+        parent.Append(menu=self.HelpMenu, title=_('Help'))
 
     def _init_coll_FileMenu_Items(self, parent):
         parent.Append(help='', id=wx.ID_NEW,
-              kind=wx.ITEM_NORMAL, text='New\tCTRL+N')
+              kind=wx.ITEM_NORMAL, text=_('New\tCTRL+N'))
         parent.Append(help='', id=wx.ID_OPEN,
-              kind=wx.ITEM_NORMAL, text='Open\tCTRL+O')
+              kind=wx.ITEM_NORMAL, text=_('Open\tCTRL+O'))
         parent.Append(help='', id=wx.ID_CLOSE,
-              kind=wx.ITEM_NORMAL, text='Close\tCTRL+W')
+              kind=wx.ITEM_NORMAL, text=_('Close\tCTRL+W'))
         parent.AppendSeparator()
         parent.Append(help='', id=wx.ID_SAVE,
-              kind=wx.ITEM_NORMAL, text='Save\tCTRL+S')
+              kind=wx.ITEM_NORMAL, text=_('Save\tCTRL+S'))
         parent.AppendSeparator()
         parent.Append(help='', id=wx.ID_EXIT,
-              kind=wx.ITEM_NORMAL, text='Exit')
+              kind=wx.ITEM_NORMAL, text=_('Exit'))
         self.Bind(wx.EVT_MENU, self.OnNewProjectMenu, id=wx.ID_NEW)
         self.Bind(wx.EVT_MENU, self.OnOpenProjectMenu, id=wx.ID_OPEN)
         self.Bind(wx.EVT_MENU, self.OnCloseProjectMenu, id=wx.ID_CLOSE)
@@ -155,12 +206,12 @@
 
     def _init_coll_NetworkMenu_Items(self, parent):
         parent.Append(help='', id=wx.ID_ADD,
-              kind=wx.ITEM_NORMAL, text='Add Slave Node')
+              kind=wx.ITEM_NORMAL, text=_('Add Slave Node'))
         parent.Append(help='', id=wx.ID_DELETE,
-              kind=wx.ITEM_NORMAL, text='Remove Slave Node')
+              kind=wx.ITEM_NORMAL, text=_('Remove Slave Node'))
         parent.AppendSeparator()
         parent.Append(help='', id=ID_NETWORKEDITNETWORKMENUBUILDMASTER,
-              kind=wx.ITEM_NORMAL, text='Build Master Dictionary')
+              kind=wx.ITEM_NORMAL, text=_('Build Master Dictionary'))
         self.Bind(wx.EVT_MENU, self.OnAddSlaveMenu, id=wx.ID_ADD)
         self.Bind(wx.EVT_MENU, self.OnRemoveSlaveMenu, id=wx.ID_DELETE)
 ##        self.Bind(wx.EVT_MENU, self.OnBuildMasterMenu,
@@ -168,21 +219,21 @@
 
     def _init_coll_EditMenu_Items(self, parent):
         parent.Append(help='', id=wx.ID_REFRESH,
-              kind=wx.ITEM_NORMAL, text='Refresh\tCTRL+R')
+              kind=wx.ITEM_NORMAL, text=_('Refresh\tCTRL+R'))
         parent.AppendSeparator()
         parent.Append(help='', id=wx.ID_UNDO,
-              kind=wx.ITEM_NORMAL, text='Undo\tCTRL+Z')
+              kind=wx.ITEM_NORMAL, text=_('Undo\tCTRL+Z'))
         parent.Append(help='', id=wx.ID_REDO,
-              kind=wx.ITEM_NORMAL, text='Redo\tCTRL+Y')
+              kind=wx.ITEM_NORMAL, text=_('Redo\tCTRL+Y'))
         parent.AppendSeparator()
         parent.Append(help='', id=ID_NETWORKEDITEDITMENUNODEINFOS,
-              kind=wx.ITEM_NORMAL, text='Node infos')
+              kind=wx.ITEM_NORMAL, text=_('Node infos'))
         parent.Append(help='', id=ID_NETWORKEDITEDITMENUDS301PROFILE,
-              kind=wx.ITEM_NORMAL, text='DS-301 Profile')
+              kind=wx.ITEM_NORMAL, text=_('DS-301 Profile'))
         parent.Append(help='', id=ID_NETWORKEDITEDITMENUDS302PROFILE,
-              kind=wx.ITEM_NORMAL, text='DS-302 Profile')
+              kind=wx.ITEM_NORMAL, text=_('DS-302 Profile'))
         parent.Append(help='', id=ID_NETWORKEDITEDITMENUOTHERPROFILE,
-              kind=wx.ITEM_NORMAL, text='Other Profile')
+              kind=wx.ITEM_NORMAL, text=_('Other Profile'))
         self.Bind(wx.EVT_MENU, self.OnRefreshMenu, id=wx.ID_REFRESH)
         self.Bind(wx.EVT_MENU, self.OnUndoMenu, id=wx.ID_UNDO)
         self.Bind(wx.EVT_MENU, self.OnRedoMenu, id=wx.ID_REDO)
@@ -197,17 +248,17 @@
 
     def _init_coll_AddMenu_Items(self, parent):
         parent.Append(help='', id=ID_NETWORKEDITADDMENUSDOSERVER,
-              kind=wx.ITEM_NORMAL, text='SDO Server')
+              kind=wx.ITEM_NORMAL, text=_('SDO Server'))
         parent.Append(help='', id=ID_NETWORKEDITADDMENUSDOCLIENT,
-              kind=wx.ITEM_NORMAL, text='SDO Client')
+              kind=wx.ITEM_NORMAL, text=_('SDO Client'))
         parent.Append(help='', id=ID_NETWORKEDITADDMENUPDOTRANSMIT,
-              kind=wx.ITEM_NORMAL, text='PDO Transmit')
+              kind=wx.ITEM_NORMAL, text=_('PDO Transmit'))
         parent.Append(help='', id=ID_NETWORKEDITADDMENUPDORECEIVE,
-              kind=wx.ITEM_NORMAL, text='PDO Receive')
+              kind=wx.ITEM_NORMAL, text=_('PDO Receive'))
         parent.Append(help='', id=ID_NETWORKEDITADDMENUMAPVARIABLE,
-              kind=wx.ITEM_NORMAL, text='Map Variable')
+              kind=wx.ITEM_NORMAL, text=_('Map Variable'))
         parent.Append(help='', id=ID_NETWORKEDITADDMENUUSERTYPE,
-              kind=wx.ITEM_NORMAL, text='User Type')
+              kind=wx.ITEM_NORMAL, text=_('User Type'))
         self.Bind(wx.EVT_MENU, self.OnAddSDOServerMenu,
               id=ID_NETWORKEDITADDMENUSDOSERVER)
         self.Bind(wx.EVT_MENU, self.OnAddSDOClientMenu,
@@ -223,14 +274,14 @@
 
     def _init_coll_HelpMenu_Items(self, parent):
         parent.Append(help='', id=wx.ID_HELP,
-              kind=wx.ITEM_NORMAL, text='DS-301 Standard\tF1')
+              kind=wx.ITEM_NORMAL, text=_('DS-301 Standard\tF1'))
         self.Bind(wx.EVT_MENU, self.OnHelpDS301Menu, id=wx.ID_HELP)
         parent.Append(help='', id=wx.ID_HELP_CONTEXT,
-              kind=wx.ITEM_NORMAL, text='CAN Festival Docs\tF2')
+              kind=wx.ITEM_NORMAL, text=_('CAN Festival Docs\tF2'))
         self.Bind(wx.EVT_MENU, self.OnHelpCANFestivalMenu, id=wx.ID_HELP_CONTEXT)
         if Html_Window and self.ModeSolo:
             parent.Append(help='', id=wx.ID_ABOUT,
-                  kind=wx.ITEM_NORMAL, text='About')
+                  kind=wx.ITEM_NORMAL, text=_('About'))
             self.Bind(wx.EVT_MENU, self.OnAboutMenu, id=wx.ID_ABOUT)
 
     def _init_coll_HelpBar_Fields(self, parent):
@@ -264,7 +315,7 @@
     def _init_ctrls(self, prnt):
         wx.Frame.__init__(self, id=ID_NETWORKEDIT, name='networkedit',
               parent=prnt, pos=wx.Point(149, 178), size=wx.Size(1000, 700),
-              style=wx.DEFAULT_FRAME_STYLE, title='Networkedit')
+              style=wx.DEFAULT_FRAME_STYLE, title=_('Networkedit'))
         self._init_utils()
         self.SetClientSize(wx.Size(1000, 700))
         self.SetMenuBar(self.MenuBar)
@@ -401,7 +452,7 @@
             defaultpath = os.path.dirname(self.NodeList.GetRoot())
         else:
             defaultpath = os.getcwd()
-        dialog = wx.DirDialog(self , "Choose a project", defaultpath, wx.DD_NEW_DIR_BUTTON)
+        dialog = wx.DirDialog(self , _("Choose a project"), defaultpath, wx.DD_NEW_DIR_BUTTON)
         if dialog.ShowModal() == wx.ID_OK:
             projectpath = dialog.GetPath()
             if os.path.isdir(projectpath) and len(os.listdir(projectpath)) == 0:
@@ -419,7 +470,7 @@
                     self.RefreshProfileMenu()
                     self.RefreshMainMenu()
                 else:
-                    message = wx.MessageDialog(self, result, "ERROR", wx.OK|wx.ICON_ERROR)
+                    message = wx.MessageDialog(self, result, _("ERROR"), wx.OK|wx.ICON_ERROR)
                     message.ShowModal()
                     message.Destroy()
         event.Skip()
@@ -429,7 +480,7 @@
             defaultpath = os.path.dirname(self.NodeList.GetRoot())
         else:
             defaultpath = os.getcwd()
-        dialog = wx.DirDialog(self , "Choose a project", defaultpath, 0)
+        dialog = wx.DirDialog(self , _("Choose a project"), defaultpath, 0)
         if dialog.ShowModal() == wx.ID_OK:
             projectpath = dialog.GetPath()
             if os.path.isdir(projectpath):
@@ -447,7 +498,7 @@
                     self.RefreshProfileMenu()
                     self.RefreshMainMenu()
                 else:
-                    message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
+                    message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
                     message.ShowModal()
                     message.Destroy()
         dialog.Destroy()
@@ -459,7 +510,7 @@
         else:
             result = self.NodeList.SaveProject()
             if result:
-                message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
+                message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
                 message.ShowModal()
                 message.Destroy()
         event.Skip()
@@ -467,13 +518,13 @@
     def OnCloseProjectMenu(self, event):
         if self.NodeList:
             if self.NodeList.HasChanged():
-                dialog = wx.MessageDialog(self, "There are changes, do you want to save?",  "Close Project", wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
+                dialog = wx.MessageDialog(self, _("There are changes, do you want to save?"), _("Close Project"), wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
                 answer = dialog.ShowModal()
                 dialog.Destroy()
                 if answer == wx.ID_YES:
                     result = self.NodeList.SaveProject()
                     if result:
-                        message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
+                        message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
                         message.ShowModal()
                         message.Destroy()
                 elif answer == wx.ID_NO:
@@ -505,7 +556,7 @@
                 self.NetworkNodes.SetSelection(idx)
                 self.RefreshBufferState()
             else:
-                message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
+                message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
                 message.ShowModal()
                 message.Destroy()
         dialog.Destroy()
@@ -514,7 +565,7 @@
     def OnRemoveSlaveMenu(self, event):
         slavenames = self.NodeList.GetSlaveNames()
         slaveids = self.NodeList.GetSlaveIDs()
-        dialog = wx.SingleChoiceDialog(self, "Choose a slave to remove", "Remove slave", slavenames)
+        dialog = wx.SingleChoiceDialog(self, _("Choose a slave to remove"), _("Remove slave"), slavenames)
         if dialog.ShowModal() == wx.ID_OK:
             choice = dialog.GetSelection()
             result = self.NodeList.RemoveSlaveNode(slaveids[choice])
@@ -529,7 +580,7 @@
                         self.NodeList.SetCurrentSelected(slaveids[new_selection - 1])
                     self.RefreshBufferState()
             else:
-                message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
+                message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
                 message.ShowModal()
                 message.Destroy()
         event.Skip()
@@ -540,9 +591,9 @@
 
     def RefreshTitle(self):
         if self.NodeList != None:
-            self.SetTitle("Networkedit - %s"%self.NodeList.GetNetworkName())
+            self.SetTitle(_("Networkedit - %s")%self.NodeList.GetNetworkName())
         else:
-            self.SetTitle("Networkedit")
+            self.SetTitle(_("Networkedit"))
 
     def OnRefreshMenu(self, event):
         self.RefreshCurrentIndexList()
@@ -576,22 +627,22 @@
             if selection:
                 index, subIndex = selection
                 if self.NodeList.IsCurrentEntry(index):
-                    self.HelpBar.SetStatusText("Index: 0x%04X"%index, 0)
-                    self.HelpBar.SetStatusText("Subindex: 0x%02X"%subIndex, 1)
+                    self.HelpBar.SetStatusText(_("Index: 0x%04X")%index, 0)
+                    self.HelpBar.SetStatusText(_("Subindex: 0x%02X")%subIndex, 1)
                     entryinfos = self.NodeList.GetEntryInfos(index)
                     name = entryinfos["name"]
-                    category = "Optional"
+                    category = _("Optional")
                     if entryinfos["need"]:
-                        category = "Mandatory"
+                        category = _("Mandatory")
                     struct = "VAR"
                     number = ""
                     if entryinfos["struct"] & OD_IdenticalIndexes:
-                        number = " possibly defined %d times"%entryinfos["nbmax"]
+                        number = _(" possibly defined %d times")%entryinfos["nbmax"]
                     if entryinfos["struct"] & OD_IdenticalSubindexes:
                         struct = "REC"
                     elif entryinfos["struct"] & OD_MultipleSubindexes:
                         struct = "ARRAY"
-                    text = "%s: %s entry of struct %s%s."%(name,category,struct,number)
+                    text = _("%s: %s entry of struct %s%s.")%(name,category,struct,number)
                     self.HelpBar.SetStatusText(text, 2)
                 else:
                     for i in xrange(3):
@@ -644,7 +695,7 @@
                 additem = self.AddMenu.FindItemByPosition(6)
                 self.AddMenu.Delete(additem.GetId())
             if profile not in ("None", "DS-301"):
-                edititem.SetText("%s Profile"%profile)
+                edititem.SetText(_("%s Profile")%profile)
                 edititem.Enable(True)
                 self.AddMenu.AppendSeparator()
                 for text, indexes in self.Manager.GetCurrentSpecificMenu():
@@ -652,7 +703,7 @@
                     self.AddMenu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=text)
                     self.Bind(wx.EVT_MENU, self.GetProfileCallBack(text), id=new_id)
             else:
-                edititem.SetText("Other Profile")
+                edititem.SetText(_("Other Profile"))
                 edititem.Enable(False)
 
     def GetProfileCallBack(self, text):
@@ -706,13 +757,13 @@
                 index, subIndex = result
                 result = OpenPDFDocIndex(index, ScriptDirectory)
                 if isinstance(result, (StringType, UnicodeType)):
-                    message = wx.MessageDialog(self, result, "ERROR", wx.OK|wx.ICON_ERROR)
+                    message = wx.MessageDialog(self, result, _("ERROR"), wx.OK|wx.ICON_ERROR)
                     message.ShowModal()
                     message.Destroy()
         if not find_index:
             result = OpenPDFDocIndex(None, ScriptDirectory)
             if isinstance(result, (StringType, UnicodeType)):
-                message = wx.MessageDialog(self, result, "ERROR", wx.OK|wx.ICON_ERROR)
+                message = wx.MessageDialog(self, result, _("ERROR"), wx.OK|wx.ICON_ERROR)
                 message.ShowModal()
                 message.Destroy()
         event.Skip()
@@ -729,7 +780,7 @@
         event.Skip()
 
     def OnAboutMenu(self, event):
-        self.OpenHtmlFrame("About CAN Festival", os.path.join(ScriptDirectory, "doc/about.html"), wx.Size(500, 450))
+        self.OpenHtmlFrame(_("About CAN Festival"), os.path.join(ScriptDirectory, "doc/about.html"), wx.Size(500, 450))
         event.Skip()
 
     def OpenHtmlFrame(self, title, file, size):
@@ -747,16 +798,16 @@
 
     def OnCommunicationMenu(self, event):
         dictionary,current = self.Manager.GetCurrentCommunicationLists()
-        self.EditProfile("Edit DS-301 Profile", dictionary, current)
+        self.EditProfile(_("Edit DS-301 Profile"), dictionary, current)
         event.Skip()
     
     def OnOtherCommunicationMenu(self, event):
         dictionary,current = self.Manager.GetCurrentDS302Lists()
-        self.EditProfile("Edit DS-302 Profile", dictionary, current)
+        self.EditProfile(_("Edit DS-302 Profile"), dictionary, current)
         event.Skip()
     
     def OnEditProfileMenu(self, event):
-        title = "Edit %s Profile"%self.Manager.GetCurrentProfileName()
+        title = _("Edit %s Profile")%self.Manager.GetCurrentProfileName()
         dictionary,current = self.Manager.GetCurrentProfileLists()
         self.EditProfile(title, dictionary, current)
         event.Skip()
@@ -821,12 +872,12 @@
                     self.RefreshBufferState()
                     self.RefreshCurrentIndexList()
                 else:
-                    message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
+                    message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
                     message.ShowModal()
                     message.Destroy()
             dialog.Destroy()
         else:
-            message = wx.MessageDialog(self, result, "No map variable index left!", wx.OK|wx.ICON_ERROR)
+            message = wx.MessageDialog(self, result, _("No map variable index left!"), wx.OK|wx.ICON_ERROR)
             message.ShowModal()
             message.Destroy()
         
@@ -840,7 +891,7 @@
                 self.RefreshBufferState()
                 self.RefreshCurrentIndexList()
             else:
-                message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
+                message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
                 message.ShowModal()
                 message.Destroy()
         dialog.Destroy()
@@ -858,12 +909,12 @@
 def Display_Exception_Dialog(e_type,e_value,e_tb):
     trcbck_lst = []
     for i,line in enumerate(traceback.extract_tb(e_tb)):
-        trcbck = " " + str(i+1) + ". "
+        trcbck = " " + str(i+1) + _(". ")
         if line[0].find(os.getcwd()) == -1:
-            trcbck += "file : " + str(line[0]) + ",   "
+            trcbck += _("file : ") + str(line[0]) + _(",   ")
         else:
-            trcbck += "file : " + str(line[0][len(os.getcwd()):]) + ",   "
-        trcbck += "line : " + str(line[1]) + ",   " + "function : " + str(line[2])
+            trcbck += _("file : ") + str(line[0][len(os.getcwd()):]) + _(",   ")
+        trcbck += _("line : ") + str(line[1]) + _(",   ") + _("function : ") + str(line[2])
         trcbck_lst.append(trcbck)
         
     # Allow clicking....
@@ -872,7 +923,7 @@
         cap.ReleaseMouse()
 
     dlg = wx.SingleChoiceDialog(None, 
-        """
+        _("""
 An error happens.
 
 Click on OK for saving an error report.
@@ -883,9 +934,9 @@
 
 
 Error:
-""" +
-        str(e_type) + " : " + str(e_value), 
-        "Error",
+""") +
+        str(e_type) + _(" : ") + str(e_value), 
+        _("Error"),
         trcbck_lst)
     try:
         res = (dlg.ShowModal() == wx.ID_OK)
@@ -895,7 +946,7 @@
     return res
 
 def Display_Error_Dialog(e_value):
-    message = wx.MessageDialog(None, str(e_value), "Error", wx.OK|wx.ICON_ERROR)
+    message = wx.MessageDialog(None, str(e_value), _("Error"), wx.OK|wx.ICON_ERROR)
     message.ShowModal()
     message.Destroy()
 
@@ -953,31 +1004,6 @@
     sys.excepthook = handle_exception
 
 if __name__ == '__main__':
-    def usage():
-        print "\nUsage of networkedit.py :"
-        print "\n   %s [Projectpath]\n"%sys.argv[0]
-
-    try:
-        opts, args = getopt.getopt(sys.argv[1:], "h", ["help"])
-    except getopt.GetoptError:
-        # print help information and exit:
-        usage()
-        sys.exit(2)
-
-    for o, a in opts:
-        if o in ("-h", "--help"):
-            usage()
-            sys.exit()
-
-    if len(args) == 0:
-        projectOpen = None 
-    elif len(args) == 1:
-        projectOpen = args[0]
-    else:
-        usage()
-        sys.exit(2)
-    
-    app = wx.PySimpleApp()
     wx.InitAllImageHandlers()
     
     # Install a exception handle for bug reports
--- a/objdictgen/nodelist.py	Mon Jul 20 16:11:20 2009 +0200
+++ b/objdictgen/nodelist.py	Mon Jul 27 16:29:59 2009 +0200
@@ -96,7 +96,7 @@
         
         self.Root = root
         if not os.path.exists(self.Root):
-            return "\"%s\" folder doesn't exist"%self.Root
+            return _("\"%s\" folder doesn't exist")%self.Root
         
         self.EDSFolder = os.path.join(self.Root, "eds")
         if not os.path.exists(self.EDSFolder):
@@ -134,7 +134,7 @@
         dir, file = os.path.split(edspath)
         eds = os.path.join(self.EDSFolder, file)
         if not force and os.path.isfile(eds):
-            return "EDS file already imported"
+            return _("EDS file already imported")
         else:
             shutil.copy(edspath, self.EDSFolder)
             return self.LoadEDS(file)
@@ -155,14 +155,14 @@
             self.Changed = True
             return None
         else:
-            return "\"%s\" EDS file is not available"%eds
+            return _("\"%s\" EDS file is not available")%eds
     
     def RemoveSlaveNode(self, index):
         if index in self.SlaveNodes.keys():
             self.SlaveNodes.pop(index)
             return None
         else:
-            return "Node with \"0x%2.2X\" ID doesn't exist"
+            return _("Node with \"0x%2.2X\" ID doesn't exist")
     
     def LoadMasterNode(self, netname = None):
         if netname:
@@ -185,7 +185,7 @@
         if self.Manager.SaveCurrentInFile(masterpath):
             return None
         else:
-            return "Fail to save Master Node"
+            return _("Fail to save Master Node")
     
     def LoadSlaveNodes(self, netname = None):
         cpjpath = os.path.join(self.Root, "nodelist.cpj")
@@ -209,7 +209,7 @@
                                 return result        
                 self.Changed = False
             except SyntaxError, message:
-                return "Unable to load CPJ file\n%s"%message
+                return _("Unable to load CPJ file\n%s")%message
         return None
     
     def SaveNodeList(self, netname = None):
@@ -225,14 +225,14 @@
             self.Changed = False
             return None
         except:
-            return "Fail to save node list"
+            return _("Fail to save node list")
     
     def GetSlaveNodeEntry(self, nodeid, index, subindex = None):
         if nodeid in self.SlaveNodes.keys():
             self.SlaveNodes[nodeid]["Node"].SetNodeID(nodeid)
             return self.SlaveNodes[nodeid]["Node"].GetEntry(index, subindex)
         else:
-            return "Node 0x%2.2X doesn't exist"%nodeid
+            return _("Node 0x%2.2X doesn't exist")%nodeid
 
     def GetMasterNodeEntry(self, index, subindex = None):
         return self.Manager.GetCurrentEntry(index, subindex)
@@ -300,7 +300,7 @@
                             validindexes.append((node.GetEntryName(index), index))
                     return validindexes
                 else:
-                    print "Can't find node"
+                    print _("Can't find node")
         return []
     
     def GetCurrentEntryValues(self, index):
@@ -310,7 +310,7 @@
                 node.SetNodeID(self.CurrentSelected)
                 return self.Manager.GetNodeEntryValues(node, index)
             else:
-                print "Can't find node"
+                print _("Can't find node")
         return [], []
     
     def AddToMasterDCF(self, node_id, index, subindex, size, value):
--- a/objdictgen/nodemanager.py	Mon Jul 20 16:11:20 2009 +0200
+++ b/objdictgen/nodemanager.py	Mon Jul 27 16:29:59 2009 +0200
@@ -215,9 +215,9 @@
                             self.CurrentNode.SetDS302Profile(Mapping)
                             self.CurrentNode.ExtendSpecificMenu(AddMenuEntries)
                         except:
-                            return "Problem with DS-302! Syntax Error."
+                            return _("Problem with DS-302! Syntax Error.")
                     else:
-                        return "Couldn't find DS-302 in 'config' folder!"
+                        return _("Couldn't find DS-302 in 'config' folder!")
                 elif option == "GenSYNC":
                     AddIndexList.extend([0x1005, 0x1006])
                 elif option == "Emergency":
@@ -261,7 +261,7 @@
                 node.SetSpecificMenu(AddMenuEntries)
                 return None
             except:
-                return "Syntax Error\nBad OD Profile file!"
+                return _("Syntax Error\nBad OD Profile file!")
         else:
             # Default profile
             node.SetProfileName("None")
@@ -285,7 +285,7 @@
             self.SetCurrentFilePath(filepath)
             return index
         except:
-            return "Unable to load file \"%s\"!"%filepath
+            return _("Unable to load file \"%s\"!")%filepath
 
     """
     Save current node in  a file
@@ -624,9 +624,9 @@
                     self.BufferCurrentNode()
                 return None
             else:
-                return "Index 0x%04X already defined!"%index
-        else:
-            return "Index 0x%04X isn't a valid index for Map Variable!"%index
+                return _("Index 0x%04X already defined!")%index
+        else:
+            return _("Index 0x%04X isn't a valid index for Map Variable!")%index
 
     def AddUserTypeToCurrent(self, type, min, max, length):
         index = 0xA0
@@ -656,7 +656,7 @@
             self.BufferCurrentNode()
             return None
         else:
-            return "Too many User Types have already been defined!"
+            return _("Too many User Types have already been defined!")
 
 #-------------------------------------------------------------------------------
 #                      Modify Entry and Mapping Functions
@@ -850,7 +850,7 @@
         self.FilePaths[self.NodeIndex] = filepath
         if filepath == "":
             self.LastNewIndex += 1
-            self.FileNames[self.NodeIndex] = "Unnamed%d"%self.LastNewIndex
+            self.FileNames[self.NodeIndex] = _("Unnamed%d")%self.LastNewIndex
         else:
             self.FileNames[self.NodeIndex] = os.path.splitext(os.path.basename(filepath))[0]
                 
--- a/objdictgen/objdictedit.py	Mon Jul 20 16:11:20 2009 +0200
+++ b/objdictgen/objdictedit.py	Mon Jul 27 16:29:59 2009 +0200
@@ -26,7 +26,52 @@
 from types import *
 import os, re, platform, sys, time, traceback, getopt
 
-__version__ = "$Revision$"
+__version__ = "$Revision: 1.48 $"
+
+if __name__ == '__main__':
+    def usage():
+        print _("\nUsage of objdictedit.py :")
+        print "\n   %s [Filepath, ...]\n"%sys.argv[0]
+
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], "h", ["help"])
+    except getopt.GetoptError:
+        # print help information and exit:
+        usage()
+        sys.exit(2)
+
+    for o, a in opts:
+        if o in ("-h", "--help"):
+            usage()
+            sys.exit()
+    
+    app = wx.PySimpleApp()
+
+ScriptDirectory = os.path.split(os.path.realpath(__file__))[0]
+
+# Import module for internationalization
+import gettext
+import __builtin__
+
+# Get folder containing translation files
+localedir = os.path.join(ScriptDirectory,"locale")
+# Get the default language
+langid = wx.LANGUAGE_DEFAULT
+# Define translation domain (name of translation files)
+domain = "objdictgen"
+
+# Define locale for wx
+loc = __builtin__.__dict__.get('loc', None)
+if loc is None:
+    loc = wx.Locale(langid)
+    __builtin__.__dict__['loc'] = loc
+# Define location for searching translation files
+loc.AddCatalogLookupPathPrefix(localedir)
+# Define locale domain
+loc.AddCatalog(domain)
+
+if __name__ == '__main__':
+    __builtin__.__dict__['_'] = wx.GetTranslation
 
 from node import OD_Subindex, OD_MultipleSubindexes, OD_IdenticalSubindexes, OD_IdenticalIndexes
 
@@ -97,7 +142,7 @@
             try:
                 import webbrowser
             except ImportError:
-                wx.MessageBox('Please point your browser at: %s' % url)
+                wx.MessageBox(_('Please point your browser at: %s') % url)
             else:
                 webbrowser.open(url)
 
@@ -105,8 +150,6 @@
 except:
     Html_Window = False
 
-ScriptDirectory = os.path.split(os.path.realpath(__file__))[0]
-
 [ID_OBJDICTEDIT, ID_OBJDICTEDITFILEOPENED, 
  ID_OBJDICTEDITHELPBAR,
 ] = [wx.NewId() for _init_ctrls in range(3)]
@@ -127,33 +170,33 @@
 class objdictedit(wx.Frame):
     def _init_coll_MenuBar_Menus(self, parent):
         if self.ModeSolo:
-            parent.Append(menu=self.FileMenu, title='File')
-        parent.Append(menu=self.EditMenu, title='Edit')
-        parent.Append(menu=self.AddMenu, title='Add')
-        parent.Append(menu=self.HelpMenu, title='Help')
+            parent.Append(menu=self.FileMenu, title=_('File'))
+        parent.Append(menu=self.EditMenu, title=_('Edit'))
+        parent.Append(menu=self.AddMenu, title=_('Add'))
+        parent.Append(menu=self.HelpMenu, title=_('Help'))
 
     def _init_coll_FileMenu_Items(self, parent):
         parent.Append(help='', id=wx.ID_NEW,
-              kind=wx.ITEM_NORMAL, text='New\tCTRL+N')
+              kind=wx.ITEM_NORMAL, text=_('New\tCTRL+N'))
         parent.Append(help='', id=wx.ID_OPEN,
-              kind=wx.ITEM_NORMAL, text='Open\tCTRL+O')
+              kind=wx.ITEM_NORMAL, text=_('Open\tCTRL+O'))
         parent.Append(help='', id=wx.ID_CLOSE,
-              kind=wx.ITEM_NORMAL, text='Close\tCTRL+W')
+              kind=wx.ITEM_NORMAL, text=_('Close\tCTRL+W'))
         parent.AppendSeparator()
         parent.Append(help='', id=wx.ID_SAVE,
-              kind=wx.ITEM_NORMAL, text='Save\tCTRL+S')
+              kind=wx.ITEM_NORMAL, text=_('Save\tCTRL+S'))
         parent.Append(help='', id=wx.ID_SAVEAS,
-              kind=wx.ITEM_NORMAL, text='Save As...\tALT+S')
+              kind=wx.ITEM_NORMAL, text=_('Save As...\tALT+S'))
         parent.AppendSeparator()
         parent.Append(help='', id=ID_OBJDICTEDITFILEMENUIMPORTEDS,
-              kind=wx.ITEM_NORMAL, text='Import EDS file')
+              kind=wx.ITEM_NORMAL, text=_('Import EDS file'))
         parent.Append(help='', id=ID_OBJDICTEDITFILEMENUEXPORTEDS,
-              kind=wx.ITEM_NORMAL, text='Export to EDS file')
+              kind=wx.ITEM_NORMAL, text=_('Export to EDS file'))
         parent.Append(help='', id=ID_OBJDICTEDITFILEMENUEXPORTC,
-              kind=wx.ITEM_NORMAL, text='Build Dictionary\tCTRL+B')
+              kind=wx.ITEM_NORMAL, text=_('Build Dictionary\tCTRL+B'))
         parent.AppendSeparator()
         parent.Append(help='', id=wx.ID_EXIT,
-              kind=wx.ITEM_NORMAL, text='Exit')
+              kind=wx.ITEM_NORMAL, text=_('Exit'))
         self.Bind(wx.EVT_MENU, self.OnNewMenu, id=wx.ID_NEW)
         self.Bind(wx.EVT_MENU, self.OnOpenMenu, id=wx.ID_OPEN)
         self.Bind(wx.EVT_MENU, self.OnCloseMenu, id=wx.ID_CLOSE)
@@ -169,21 +212,21 @@
 
     def _init_coll_EditMenu_Items(self, parent):
         parent.Append(help='', id=wx.ID_REFRESH,
-              kind=wx.ITEM_NORMAL, text='Refresh\tCTRL+R')
+              kind=wx.ITEM_NORMAL, text=_('Refresh\tCTRL+R'))
         parent.AppendSeparator()
         parent.Append(help='', id=wx.ID_UNDO,
-              kind=wx.ITEM_NORMAL, text='Undo\tCTRL+Z')
+              kind=wx.ITEM_NORMAL, text=_('Undo\tCTRL+Z'))
         parent.Append(help='', id=wx.ID_REDO,
-              kind=wx.ITEM_NORMAL, text='Redo\tCTRL+Y')
+              kind=wx.ITEM_NORMAL, text=_('Redo\tCTRL+Y'))
         parent.AppendSeparator()
         parent.Append(help='', id=ID_OBJDICTEDITEDITMENUNODEINFOS,
-              kind=wx.ITEM_NORMAL, text='Node infos')
+              kind=wx.ITEM_NORMAL, text=_('Node infos'))
         parent.Append(help='', id=ID_OBJDICTEDITEDITMENUDS301PROFILE,
-              kind=wx.ITEM_NORMAL, text='DS-301 Profile')
+              kind=wx.ITEM_NORMAL, text=_('DS-301 Profile'))
         parent.Append(help='', id=ID_OBJDICTEDITEDITMENUDS302PROFILE,
-              kind=wx.ITEM_NORMAL, text='DS-302 Profile')
+              kind=wx.ITEM_NORMAL, text=_('DS-302 Profile'))
         parent.Append(help='', id=ID_OBJDICTEDITEDITMENUOTHERPROFILE,
-              kind=wx.ITEM_NORMAL, text='Other Profile')
+              kind=wx.ITEM_NORMAL, text=_('Other Profile'))
         self.Bind(wx.EVT_MENU, self.OnRefreshMenu, id=wx.ID_REFRESH)
         self.Bind(wx.EVT_MENU, self.OnUndoMenu, id=wx.ID_UNDO)
         self.Bind(wx.EVT_MENU, self.OnRedoMenu, id=wx.ID_REDO)
@@ -198,17 +241,17 @@
 
     def _init_coll_AddMenu_Items(self, parent):
         parent.Append(help='', id=ID_OBJDICTEDITADDMENUSDOSERVER,
-              kind=wx.ITEM_NORMAL, text='SDO Server')
+              kind=wx.ITEM_NORMAL, text=_('SDO Server'))
         parent.Append(help='', id=ID_OBJDICTEDITADDMENUSDOCLIENT,
-              kind=wx.ITEM_NORMAL, text='SDO Client')
+              kind=wx.ITEM_NORMAL, text=_('SDO Client'))
         parent.Append(help='', id=ID_OBJDICTEDITADDMENUPDOTRANSMIT,
-              kind=wx.ITEM_NORMAL, text='PDO Transmit')
+              kind=wx.ITEM_NORMAL, text=_('PDO Transmit'))
         parent.Append(help='', id=ID_OBJDICTEDITADDMENUPDORECEIVE,
-              kind=wx.ITEM_NORMAL, text='PDO Receive')
+              kind=wx.ITEM_NORMAL, text=_('PDO Receive'))
         parent.Append(help='', id=ID_OBJDICTEDITADDMENUMAPVARIABLE,
-              kind=wx.ITEM_NORMAL, text='Map Variable')
+              kind=wx.ITEM_NORMAL, text=_('Map Variable'))
         parent.Append(help='', id=ID_OBJDICTEDITADDMENUUSERTYPE,
-              kind=wx.ITEM_NORMAL, text='User Type')
+              kind=wx.ITEM_NORMAL, text=_('User Type'))
         self.Bind(wx.EVT_MENU, self.OnAddSDOServerMenu,
               id=ID_OBJDICTEDITADDMENUSDOSERVER)
         self.Bind(wx.EVT_MENU, self.OnAddSDOClientMenu,
@@ -224,14 +267,14 @@
 
     def _init_coll_HelpMenu_Items(self, parent):
         parent.Append(help='', id=wx.ID_HELP,
-              kind=wx.ITEM_NORMAL, text='DS-301 Standard\tF1')
+              kind=wx.ITEM_NORMAL, text=_('DS-301 Standard\tF1'))
         self.Bind(wx.EVT_MENU, self.OnHelpDS301Menu, id=wx.ID_HELP)
         parent.Append(help='', id=wx.ID_HELP_CONTEXT,
-              kind=wx.ITEM_NORMAL, text='CAN Festival Docs\tF2')
+              kind=wx.ITEM_NORMAL, text=_('CAN Festival Docs\tF2'))
         self.Bind(wx.EVT_MENU, self.OnHelpCANFestivalMenu, id=wx.ID_HELP_CONTEXT)
         if Html_Window and self.ModeSolo:
             parent.Append(help='', id=wx.ID_ABOUT,
-                  kind=wx.ITEM_NORMAL, text='About')
+                  kind=wx.ITEM_NORMAL, text=_('About'))
             self.Bind(wx.EVT_MENU, self.OnAboutMenu, id=wx.ID_ABOUT)
 
     def _init_coll_HelpBar_Fields(self, parent):
@@ -263,7 +306,7 @@
     def _init_ctrls(self, prnt):
         wx.Frame.__init__(self, id=ID_OBJDICTEDIT, name='objdictedit',
               parent=prnt, pos=wx.Point(149, 178), size=wx.Size(1000, 700),
-              style=wx.DEFAULT_FRAME_STYLE, title='Objdictedit')
+              style=wx.DEFAULT_FRAME_STYLE, title=_('Objdictedit'))
         self._init_utils()
         self.SetClientSize(wx.Size(1000, 700))
         self.SetMenuBar(self.MenuBar)
@@ -390,13 +433,13 @@
                 index, subIndex = result
                 result = OpenPDFDocIndex(index, ScriptDirectory)
                 if isinstance(result, (StringType, UnicodeType)):
-                    message = wx.MessageDialog(self, result, "ERROR", wx.OK|wx.ICON_ERROR)
+                    message = wx.MessageDialog(self, result, _("ERROR"), wx.OK|wx.ICON_ERROR)
                     message.ShowModal()
                     message.Destroy()
         if not find_index:
             result = OpenPDFDocIndex(None, ScriptDirectory)
             if isinstance(result, (StringType, UnicodeType)):
-                message = wx.MessageDialog(self, result, "ERROR", wx.OK|wx.ICON_ERROR)
+                message = wx.MessageDialog(self, result, _("ERROR"), wx.OK|wx.ICON_ERROR)
                 message.ShowModal()
                 message.Destroy()
         event.Skip()
@@ -409,21 +452,20 @@
             if(os.path.isfile(readerexepath)):
                 os.spawnl(os.P_DETACH, readerexepath, "AcroRd32.exe", '"%s"'%os.path.join(ScriptDirectory, "doc","manual_en.pdf"))
             else:
-                message = wx.MessageDialog(self, """Check if Acrobat Reader is correctly installed on your computer""", "ERROR", wx.OK|wx.ICON_ERROR)
+                message = wx.MessageDialog(self, _("Check if Acrobat Reader is correctly installed on your computer"), _("ERROR"), wx.OK|wx.ICON_ERROR)
                 message.ShowModal()
                 message.Destroy()
-                
         else:
             try:
                 os.system("xpdf -remote CANFESTIVAL %s %d &"%(os.path.join(ScriptDirectory, "doc/manual_en.pdf"),16))
             except:
-                message = wx.MessageDialog(self, """Check if xpdf is correctly installed on your computer""", "ERROR", wx.OK|wx.ICON_ERROR)
+                message = wx.MessageDialog(self, _("Check if xpdf is correctly installed on your computer"), _("ERROR"), wx.OK|wx.ICON_ERROR)
                 message.ShowModal()
                 message.Destroy()
         event.Skip()
 
     def OnAboutMenu(self, event):
-        self.OpenHtmlFrame("About CAN Festival", os.path.join(ScriptDirectory, "doc/about.html"), wx.Size(500, 450))
+        self.OpenHtmlFrame(_("About CAN Festival"), os.path.join(ScriptDirectory, "doc/about.html"), wx.Size(500, 450))
         event.Skip()
 
     def OpenHtmlFrame(self, title, file, size):
@@ -446,7 +488,7 @@
                 self._onclose()
             event.Skip()
         elif self.Manager.OneFileHasChanged():
-            dialog = wx.MessageDialog(self, "There are changes, do you want to save?",  "Close Application", wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
+            dialog = wx.MessageDialog(self, _("There are changes, do you want to save?"),  _("Close Application"), wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
             answer = dialog.ShowModal()
             dialog.Destroy()
             if answer == wx.ID_YES:
@@ -470,9 +512,9 @@
 
     def RefreshTitle(self):
         if self.FileOpened.GetPageCount() > 0:
-            self.SetTitle("Objdictedit - %s"%self.Manager.GetCurrentFilename())
-        else:
-            self.SetTitle("Objdictedit")
+            self.SetTitle(_("Objdictedit - %s")%self.Manager.GetCurrentFilename())
+        else:
+            self.SetTitle(_("Objdictedit"))
 
     def OnRefreshMenu(self, event):
         self.RefreshCurrentIndexList()
@@ -491,22 +533,22 @@
             if selection:
                 index, subIndex = selection
                 if self.Manager.IsCurrentEntry(index):
-                    self.HelpBar.SetStatusText("Index: 0x%04X"%index, 0)
-                    self.HelpBar.SetStatusText("Subindex: 0x%02X"%subIndex, 1)
+                    self.HelpBar.SetStatusText(_("Index: 0x%04X")%index, 0)
+                    self.HelpBar.SetStatusText(_("Subindex: 0x%02X")%subIndex, 1)
                     entryinfos = self.Manager.GetEntryInfos(index)
                     name = entryinfos["name"]
-                    category = "Optional"
+                    category = _("Optional")
                     if entryinfos["need"]:
-                        category = "Mandatory"
+                        category = _("Mandatory")
                     struct = "VAR"
                     number = ""
                     if entryinfos["struct"] & OD_IdenticalIndexes:
-                        number = " possibly defined %d times"%entryinfos["nbmax"]
+                        number = _(" possibly defined %d times")%entryinfos["nbmax"]
                     if entryinfos["struct"] & OD_IdenticalSubindexes:
                         struct = "REC"
                     elif entryinfos["struct"] & OD_MultipleSubindexes:
                         struct = "ARRAY"
-                    text = "%s: %s entry of struct %s%s."%(name,category,struct,number)
+                    text = _("%s: %s entry of struct %s%s.")%(name,category,struct,number)
                     self.HelpBar.SetStatusText(text, 2)
                 else:
                     for i in xrange(3):
@@ -559,7 +601,7 @@
                 additem = self.AddMenu.FindItemByPosition(6)
                 self.AddMenu.Delete(additem.GetId())
             if profile not in ("None", "DS-301"):
-                edititem.SetText("%s Profile"%profile)
+                edititem.SetText(_("%s Profile")%profile)
                 edititem.Enable(True)
                 self.AddMenu.AppendSeparator()
                 for text, indexes in self.Manager.GetCurrentSpecificMenu():
@@ -567,7 +609,7 @@
                     self.AddMenu.Append(help='', id=new_id, kind=wx.ITEM_NORMAL, text=text)
                     self.Bind(wx.EVT_MENU, self.GetProfileCallBack(text), id=new_id)
             else:
-                edititem.SetText("Other Profile")
+                edititem.SetText(_("Other Profile"))
                 edititem.Enable(False)
         
 
@@ -620,7 +662,7 @@
                 self.RefreshProfileMenu()
                 self.RefreshMainMenu()
             else:
-                message = wx.MessageDialog(self, result, "ERROR", wx.OK|wx.ICON_ERROR)
+                message = wx.MessageDialog(self, result, _("ERROR"), wx.OK|wx.ICON_ERROR)
                 message.ShowModal()
                 message.Destroy()
         dialog.Destroy()
@@ -632,7 +674,7 @@
             directory = os.path.dirname(filepath)
         else:
             directory = os.getcwd()
-        dialog = wx.FileDialog(self, "Choose a file", directory, "",  "OD files (*.od)|*.od|All files|*.*", wx.OPEN|wx.CHANGE_DIR)
+        dialog = wx.FileDialog(self, _("Choose a file"), directory, "",  _("OD files (*.od)|*.od|All files|*.*"), wx.OPEN|wx.CHANGE_DIR)
         if dialog.ShowModal() == wx.ID_OK:
             filepath = dialog.GetPath()
             if os.path.isfile(filepath):
@@ -651,7 +693,7 @@
                     self.RefreshProfileMenu()
                     self.RefreshMainMenu()
                 else:
-                    message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
+                    message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
                     message.ShowModal()
                     message.Destroy()
         dialog.Destroy()
@@ -676,7 +718,7 @@
         elif not isinstance(result, (StringType, UnicodeType)):
             self.RefreshBufferState()
         else:
-            message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
+            message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
             message.ShowModal()
             message.Destroy()
 
@@ -686,7 +728,7 @@
             directory, filename = os.path.split(filepath)
         else:
             directory, filename = os.getcwd(), "%s.od"%self.Manager.GetCurrentNodeInfos()[0]
-        dialog = wx.FileDialog(self, "Choose a file", directory, filename,  "OD files (*.od)|*.od|All files|*.*", wx.SAVE|wx.OVERWRITE_PROMPT|wx.CHANGE_DIR)
+        dialog = wx.FileDialog(self, _("Choose a file"), directory, filename,  _("OD files (*.od)|*.od|All files|*.*"), wx.SAVE|wx.OVERWRITE_PROMPT|wx.CHANGE_DIR)
         if dialog.ShowModal() == wx.ID_OK:
             filepath = dialog.GetPath()
             if os.path.isdir(os.path.dirname(filepath)):
@@ -694,11 +736,11 @@
                 if not isinstance(result, (StringType, UnicodeType)):
                     self.RefreshBufferState()
                 else:
-                    message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
+                    message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
                     message.ShowModal()
                     message.Destroy()
             else:
-                message = wx.MessageDialog(self, "%s is not a valid folder!"%os.path.dirname(filepath), "Error", wx.OK|wx.ICON_ERROR)
+                message = wx.MessageDialog(self, _("%s is not a valid folder!")%os.path.dirname(filepath), _("Error"), wx.OK|wx.ICON_ERROR)
                 message.ShowModal()
                 message.Destroy()
         dialog.Destroy()
@@ -707,7 +749,7 @@
         answer = wx.ID_YES
         result = self.Manager.CloseCurrent()
         if not result:
-            dialog = wx.MessageDialog(self, "There are changes, do you want to save?",  "Close File", wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
+            dialog = wx.MessageDialog(self, _("There are changes, do you want to save?"),  _("Close File"), wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION)
             answer = dialog.ShowModal()
             dialog.Destroy()
             if answer == wx.ID_YES:
@@ -731,7 +773,7 @@
 #-------------------------------------------------------------------------------
 
     def OnImportEDSMenu(self, event):
-        dialog = wx.FileDialog(self, "Choose a file", os.getcwd(), "",  "EDS files (*.eds)|*.eds|All files|*.*", wx.OPEN|wx.CHANGE_DIR)
+        dialog = wx.FileDialog(self, _("Choose a file"), os.getcwd(), "",  _("EDS files (*.eds)|*.eds|All files|*.*"), wx.OPEN|wx.CHANGE_DIR)
         if dialog.ShowModal() == wx.ID_OK:
             filepath = dialog.GetPath()
             if os.path.isfile(filepath):
@@ -745,22 +787,22 @@
                     self.RefreshCurrentIndexList()
                     self.RefreshProfileMenu()
                     self.RefreshMainMenu()
-                    message = wx.MessageDialog(self, "Import successful", "Information", wx.OK|wx.ICON_INFORMATION)
+                    message = wx.MessageDialog(self, _("Import successful"), _("Information"), wx.OK|wx.ICON_INFORMATION)
                     message.ShowModal()
                     message.Destroy()
                 else:
-                    message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
+                    message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
                     message.ShowModal()
                     message.Destroy()
             else:
-                message = wx.MessageDialog(self, "\"%s\" is not a valid file!"%filepath, "Error", wx.OK|wx.ICON_ERROR)
+                message = wx.MessageDialog(self, _("\"%s\" is not a valid file!")%filepath, _("Error"), wx.OK|wx.ICON_ERROR)
                 message.ShowModal()
                 message.Destroy()
         dialog.Destroy()
         event.Skip()
 
     def OnExportEDSMenu(self, event):
-        dialog = wx.FileDialog(self, "Choose a file", os.getcwd(), self.Manager.GetCurrentNodeInfos()[0], "EDS files (*.eds)|*.eds|All files|*.*", wx.SAVE|wx.OVERWRITE_PROMPT|wx.CHANGE_DIR)
+        dialog = wx.FileDialog(self, _("Choose a file"), os.getcwd(), self.Manager.GetCurrentNodeInfos()[0], _("EDS files (*.eds)|*.eds|All files|*.*"), wx.SAVE|wx.OVERWRITE_PROMPT|wx.CHANGE_DIR)
         if dialog.ShowModal() == wx.ID_OK:
             filepath = dialog.GetPath()
             if os.path.isdir(os.path.dirname(filepath)):
@@ -769,22 +811,22 @@
                     filepath = path + ".eds"
                 result = self.Manager.ExportCurrentToEDSFile(filepath)
                 if not result:
-                    message = wx.MessageDialog(self, "Export successful", "Information", wx.OK|wx.ICON_INFORMATION)
+                    message = wx.MessageDialog(self, _("Export successful"), _("Information"), wx.OK|wx.ICON_INFORMATION)
                     message.ShowModal()
                     message.Destroy()
                 else:
-                    message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
+                    message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
                     message.ShowModal()
                     message.Destroy()
             else:
-                message = wx.MessageDialog(self, "\"%s\" is not a valid folder!"%os.path.dirname(filepath), "Error", wx.OK|wx.ICON_ERROR)
+                message = wx.MessageDialog(self, _("\"%s\" is not a valid folder!")%os.path.dirname(filepath), _("Error"), wx.OK|wx.ICON_ERROR)
                 message.ShowModal()
                 message.Destroy()
         dialog.Destroy()
         event.Skip()
 
     def OnExportCMenu(self, event):
-        dialog = wx.FileDialog(self, "Choose a file", os.getcwd(), self.Manager.GetCurrentNodeInfos()[0],  "CANFestival C files (*.c)|*.c|All files|*.*", wx.SAVE|wx.OVERWRITE_PROMPT|wx.CHANGE_DIR)
+        dialog = wx.FileDialog(self, _("Choose a file"), os.getcwd(), self.Manager.GetCurrentNodeInfos()[0],  _("CANFestival C files (*.c)|*.c|All files|*.*"), wx.SAVE|wx.OVERWRITE_PROMPT|wx.CHANGE_DIR)
         if dialog.ShowModal() == wx.ID_OK:
             filepath = dialog.GetPath()
             if os.path.isdir(os.path.dirname(filepath)):
@@ -793,15 +835,15 @@
                     filepath = path + ".c"
                 result = self.Manager.ExportCurrentToCFile(filepath)
                 if not result:
-                    message = wx.MessageDialog(self, "Export successful", "Information", wx.OK|wx.ICON_INFORMATION)
+                    message = wx.MessageDialog(self, _("Export successful"), _("Information"), wx.OK|wx.ICON_INFORMATION)
                     message.ShowModal()
                     message.Destroy()
                 else:
-                    message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
+                    message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
                     message.ShowModal()
                     message.Destroy()
             else:
-                message = wx.MessageDialog(self, "\"%s\" is not a valid folder!"%os.path.dirname(filepath), "Error", wx.OK|wx.ICON_ERROR)
+                message = wx.MessageDialog(self, _("\"%s\" is not a valid folder!")%os.path.dirname(filepath), _("Error"), wx.OK|wx.ICON_ERROR)
                 message.ShowModal()
                 message.Destroy()
         dialog.Destroy()
@@ -813,16 +855,16 @@
 
     def OnCommunicationMenu(self, event):
         dictionary,current = self.Manager.GetCurrentCommunicationLists()
-        self.EditProfile("Edit DS-301 Profile", dictionary, current)
+        self.EditProfile(_("Edit DS-301 Profile"), dictionary, current)
         event.Skip()
     
     def OnOtherCommunicationMenu(self, event):
         dictionary,current = self.Manager.GetCurrentDS302Lists()
-        self.EditProfile("Edit DS-302 Profile", dictionary, current)
+        self.EditProfile(_("Edit DS-302 Profile"), dictionary, current)
         event.Skip()
     
     def OnEditProfileMenu(self, event):
-        title = "Edit %s Profile"%self.Manager.GetCurrentProfileName()
+        title = _("Edit %s Profile")%self.Manager.GetCurrentProfileName()
         dictionary,current = self.Manager.GetCurrentProfileLists()
         self.EditProfile(title, dictionary, current)
         event.Skip()
@@ -895,12 +937,12 @@
                     self.RefreshBufferState()
                     self.RefreshCurrentIndexList()
                 else:
-                    message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
+                    message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
                     message.ShowModal()
                     message.Destroy()
             dialog.Destroy()
         else:
-            message = wx.MessageDialog(self, result, "No map variable index left!", wx.OK|wx.ICON_ERROR)
+            message = wx.MessageDialog(self, result, _("No map variable index left!"), wx.OK|wx.ICON_ERROR)
             message.ShowModal()
             message.Destroy()
         
@@ -914,7 +956,7 @@
                 self.RefreshBufferState()
                 self.RefreshCurrentIndexList()
             else:
-                message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
+                message = wx.MessageDialog(self, result, _("Error"), wx.OK|wx.ICON_ERROR)
                 message.ShowModal()
                 message.Destroy()
         dialog.Destroy()
@@ -929,12 +971,12 @@
 def Display_Exception_Dialog(e_type,e_value,e_tb):
     trcbck_lst = []
     for i,line in enumerate(traceback.extract_tb(e_tb)):
-        trcbck = " " + str(i+1) + ". "
+        trcbck = " " + str(i+1) + _(". ")
         if line[0].find(os.getcwd()) == -1:
-            trcbck += "file : " + str(line[0]) + ",   "
-        else:
-            trcbck += "file : " + str(line[0][len(os.getcwd()):]) + ",   "
-        trcbck += "line : " + str(line[1]) + ",   " + "function : " + str(line[2])
+            trcbck += _("file : ") + str(line[0]) + _(",   ")
+        else:
+            trcbck += _("file : ") + str(line[0][len(os.getcwd()):]) + _(",   ")
+        trcbck += _("line : ") + str(line[1]) + _(",   ") + _("function : ") + str(line[2])
         trcbck_lst.append(trcbck)
         
     # Allow clicking....
@@ -943,7 +985,7 @@
         cap.ReleaseMouse()
 
     dlg = wx.SingleChoiceDialog(None, 
-        """
+        _("""
 An error happens.
 
 Click on OK for saving an error report.
@@ -954,9 +996,9 @@
 
 
 Error:
-""" +
-        str(e_type) + " : " + str(e_value), 
-        "Error",
+""") +
+        str(e_type) + _(" : ") + str(e_value), 
+        _("Error"),
         trcbck_lst)
     try:
         res = (dlg.ShowModal() == wx.ID_OK)
@@ -966,7 +1008,7 @@
     return res
 
 def Display_Error_Dialog(e_value):
-    message = wx.MessageDialog(None, str(e_value), "Error", wx.OK|wx.ICON_ERROR)
+    message = wx.MessageDialog(None, str(e_value), _("Error"), wx.OK|wx.ICON_ERROR)
     message.ShowModal()
     message.Destroy()
 
@@ -1024,23 +1066,6 @@
     sys.excepthook = handle_exception
 
 if __name__ == '__main__':
-    def usage():
-        print "\nUsage of objdictedit.py :"
-        print "\n   %s [Filepath, ...]\n"%sys.argv[0]
-
-    try:
-        opts, args = getopt.getopt(sys.argv[1:], "h", ["help"])
-    except getopt.GetoptError:
-        # print help information and exit:
-        usage()
-        sys.exit(2)
-
-    for o, a in opts:
-        if o in ("-h", "--help"):
-            usage()
-            sys.exit()
-    
-    app = wx.PySimpleApp()
     wx.InitAllImageHandlers()
     
     # Install a exception handle for bug reports
--- a/objdictgen/objdictgen.py	Mon Jul 20 16:11:20 2009 +0200
+++ b/objdictgen/objdictgen.py	Mon Jul 27 16:29:59 2009 +0200
@@ -26,8 +26,10 @@
 
 from nodemanager import *
 
+_ = lambda x: x
+
 def usage():
-    print "\nUsage of objdictgen.py :"
+    print _("\nUsage of objdictgen.py :")
     print "\n   %s XMLFilePath CFilePath\n"%sys.argv[0]
 
 try:
@@ -55,7 +57,7 @@
     if fileIn != "" and fileOut != "":
         manager = NodeManager()
         if os.path.isfile(fileIn):
-            print "Parsing input file"
+            print _("Parsing input file")
             result = manager.OpenFileInCurrent(fileIn)
             if not isinstance(result, (StringType, UnicodeType)):
                 Node = result
@@ -63,12 +65,12 @@
                 print result
                 sys.exit(-1)
         else:
-            print "%s is not a valid file!"%fileIn
+            print _("%s is not a valid file!")%fileIn
             sys.exit(-1)
-        print "Writing output file"
+        print _("Writing output file")
         result = manager.ExportCurrentToCFile(fileOut)
         if isinstance(result, (UnicodeType, StringType)):
             print result
             sys.exit(-1)
-        print "All done"
+        print _("All done")
     
--- a/objdictgen/subindextable.py	Mon Jul 20 16:11:20 2009 +0200
+++ b/objdictgen/subindextable.py	Mon Jul 27 16:29:59 2009 +0200
@@ -31,10 +31,55 @@
 
 ColSizes = [75, 250, 150, 125, 100, 60, 250]
 ColAlignements = [wx.ALIGN_CENTER, wx.ALIGN_LEFT, wx.ALIGN_CENTER, wx.ALIGN_RIGHT, wx.ALIGN_CENTER, wx.ALIGN_CENTER, wx.ALIGN_LEFT]
-AccessList = "Read Only,Write Only,Read/Write"
-RAccessList = "Read Only,Read/Write"
-BoolList = "True,False"
-OptionList = "Yes,No"
+
+def GetAccessList(write=True):
+    _ = lambda x : x
+    if write:
+        return [_("Read Only"), _("Write Only"), _("Read/Write")]
+    return [_("Read Only"), _("Read/Write")]
+AccessList = ",".join(GetAccessList())
+RAccessList = ",".join(GetAccessList(False))
+ACCESS_LIST_DICT = dict([(_(access), access) for access in GetAccessList()])
+
+def GetBoolList():
+    _ = lambda x : x
+    return [_("True"), _("False")]
+BoolList = ",".join(GetBoolList())
+BOOL_LIST_DICT = dict([(_(bool), bool) for bool in GetBoolList()])
+
+def GetOptionList():
+    _ = lambda x : x
+    return [_("Yes"), _("No")]
+OptionList = ",".join(GetOptionList())
+OPTION_LIST_DICT = dict([(_(option), option) for option in GetOptionList()])
+
+[USER_TYPE, SDO_SERVER, SDO_CLIENT, 
+ PDO_TRANSMIT, PDO_RECEIVE, MAP_VARIABLE] = range(6)
+
+INDEXCHOICE_OPTIONS = {
+    USER_TYPE: (_("User Type"), 0, "AddUserType"), 
+    SDO_SERVER: (_("SDO Server"), 1, "AddSDOServerToCurrent"),
+    SDO_CLIENT: (_("SDO Client"), 1, "AddSDOClientToCurrent"),
+    PDO_RECEIVE: (_("PDO Receive"), 1, "AddPDOReceiveToCurrent"),
+    PDO_TRANSMIT: (_("PDO Transmit"), 1, "AddPDOTransmitToCurrent"),
+    MAP_VARIABLE: (_("Map Variable"), 0, "AddMapVariable")
+}
+
+INDEXCHOICE_OPTIONS_DICT = dict([(translation, option) for option, (translation, object, function) in INDEXCHOICE_OPTIONS.iteritems()])
+
+INDEXCHOICE_SECTIONS = {
+    0 : [USER_TYPE],
+    2 : [SDO_SERVER, SDO_CLIENT],
+    3 : [PDO_RECEIVE],
+    4 : [PDO_RECEIVE],
+    5 : [PDO_TRANSMIT],
+    6 : [PDO_TRANSMIT],
+    8 : [MAP_VARIABLE],
+}
+
+def GetSubindexTableColnames():
+    _ = lambda x : x
+    return [_("subindex"), _("name"), _("type"), _("value"), _("access"), _("save"), _("comment")]
 
 DictionaryOrganisation = [
     {"minIndex" : 0x0001, "maxIndex" : 0x0FFF, "name" : "Data Type Definitions"},
@@ -83,27 +128,40 @@
     def GetNumberRows(self):
         return len(self.data)
 
-    def GetColLabelValue(self, col):
+    def GetColLabelValue(self, col, translate=True):
         if col < len(self.colnames):
+            if translate:
+                return _(self.colnames[col])
             return self.colnames[col]
 
-    def GetRowLabelValues(self, row):
+    def GetRowLabelValues(self, row, translate=True):
         return row
 
     def GetValue(self, row, col):
         if row < self.GetNumberRows():
-            return str(self.data[row].get(self.GetColLabelValue(col), ""))
+            colname = self.GetColLabelValue(col, False)
+            value = unicode(self.data[row].get(colname, ""))
+            if self.editors[row][colname] in ["access", "raccess", "bool", "option"]:
+                value = _(value)
+            return value
             
     def GetEditor(self, row, col):
         if row < self.GetNumberRows():
-            return self.editors[row].get(self.GetColLabelValue(col), "")
+            return self.editors[row].get(self.GetColLabelValue(col, False), "")
     
     def GetValueByName(self, row, colname):
         return self.data[row].get(colname)
 
     def SetValue(self, row, col, value):
         if col < len(self.colnames):
-            self.data[row][self.GetColLabelValue(col)] = value
+            colname = self.GetColLabelValue(col, False)
+            if self.editors[row][colname] in ["access", "raccess"]:
+                value = ACCESS_LIST_DICT[value]
+            elif self.editors[row][colname] == "bool":
+                value = BOOL_LIST_DICT[value]
+            elif self.editors[row][colname] == "option":
+                value = OPTION_LIST_DICT[value]
+            self.data[row][colname] = value
         
     def ResetView(self, grid):
         """
@@ -152,7 +210,8 @@
             attr = wx.grid.GridCellAttr()
             attr.SetAlignment(ColAlignements[col], wx.ALIGN_CENTRE)
             grid.SetColAttr(col, attr)
-            grid.SetColSize(col, ColSizes[col])
+            grid.SetColMinimalWidth(col, ColSizes[col])
+            grid.AutoSizeColumn(col, False)
         
         typelist = None
         maplist = None
@@ -162,7 +221,7 @@
                 editor = None
                 renderer = None
                 
-                colname = self.GetColLabelValue(col)
+                colname = self.GetColLabelValue(col, False)
                 editortype = editors[colname]
                 if editortype and self.Editable:
                     grid.SetReadOnly(row, col, False)
@@ -277,15 +336,15 @@
 
     def _init_coll_SubindexGridMenu_Items(self, parent):
         parent.Append(help='', id=ID_EDITINGPANELMENU1ITEMS0,
-              kind=wx.ITEM_NORMAL, text='Add subindexes')
+              kind=wx.ITEM_NORMAL, text=_('Add subindexes'))
         parent.Append(help='', id=ID_EDITINGPANELMENU1ITEMS1,
-              kind=wx.ITEM_NORMAL, text='Delete subindexes')
+              kind=wx.ITEM_NORMAL, text=_('Delete subindexes'))
         parent.AppendSeparator()
         parent.Append(help='', id=ID_EDITINGPANELMENU1ITEMS3,
-              kind=wx.ITEM_NORMAL, text='Default value')
+              kind=wx.ITEM_NORMAL, text=_('Default value'))
         if not self.Editable:
             parent.Append(help='', id=ID_EDITINGPANELMENU1ITEMS4,
-                  kind=wx.ITEM_NORMAL, text='Add to DCF')
+                  kind=wx.ITEM_NORMAL, text=_('Add to DCF'))
         self.Bind(wx.EVT_MENU, self.OnAddSubindexMenu,
               id=ID_EDITINGPANELMENU1ITEMS0)
         self.Bind(wx.EVT_MENU, self.OnDeleteSubindexMenu,
@@ -298,11 +357,11 @@
 
     def _init_coll_IndexListMenu_Items(self, parent):
         parent.Append(help='', id=ID_EDITINGPANELINDEXLISTMENUITEMS0,
-              kind=wx.ITEM_NORMAL, text='Rename')
+              kind=wx.ITEM_NORMAL, text=_('Rename'))
         parent.Append(help='', id=ID_EDITINGPANELINDEXLISTMENUITEMS2,
-              kind=wx.ITEM_NORMAL, text='Modify')
+              kind=wx.ITEM_NORMAL, text=_('Modify'))
         parent.Append(help='', id=ID_EDITINGPANELINDEXLISTMENUITEMS1,
-              kind=wx.ITEM_NORMAL, text='Delete')
+              kind=wx.ITEM_NORMAL, text=_('Delete'))
         self.Bind(wx.EVT_MENU, self.OnRenameIndexMenu,
               id=ID_EDITINGPANELINDEXLISTMENUITEMS0)
         self.Bind(wx.EVT_MENU, self.OnDeleteIndexMenu,
@@ -382,7 +441,7 @@
               self.OnSubindexGridEditorShown)
 
         self.CallbackCheck = wx.CheckBox(id=ID_EDITINGPANELCALLBACKCHECK,
-              label='Have Callbacks', name='CallbackCheck',
+              label=_('Have Callbacks'), name='CallbackCheck',
               parent=self.SubindexGridPanel, pos=wx.Point(0, 0), size=wx.Size(152,
               24), style=0)
         self.CallbackCheck.Bind(wx.EVT_CHECKBOX, self.OnCallbackCheck,
@@ -395,9 +454,9 @@
               id=ID_EDITINGPANELINDEXLIST)
         self.IndexList.Bind(wx.EVT_RIGHT_UP, self.OnIndexListRightUp)
 
-        self.AddButton = wx.Button(id=ID_EDITINGPANELADDBUTTON, label='Add',
+        self.AddButton = wx.Button(id=ID_EDITINGPANELADDBUTTON, label=_('Add'),
               name='AddButton', parent=self.IndexListPanel, pos=wx.Point(0, 0),
-              size=wx.Size(50, 30), style=0)
+              size=wx.DefaultSize, style=0)
         self.AddButton.Bind(wx.EVT_BUTTON, self.OnAddButtonClick,
               id=ID_EDITINGPANELADDBUTTON)
 
@@ -420,7 +479,7 @@
         for values in DictionaryOrganisation:
             text = "   0x%04X-0x%04X      %s"%(values["minIndex"], values["maxIndex"], values["name"])
             self.PartList.Append(text)
-        self.Table = SubindexTable(self, [], [], ["subindex", "name", "type", "value", "access", "save", "comment"])
+        self.Table = SubindexTable(self, [], [], GetSubindexTableColnames())
         self.SubindexGrid.SetTable(self.Table)
         self.SubindexGrid.SetRowLabelSize(0)
         self.CallbackCheck.Disable()
@@ -489,18 +548,12 @@
             self.SubindexGrid.SetGridCursor(0, 0)
             selected = self.IndexChoice.GetStringSelection()
             if selected != "":
-                if selected == "User Type":
-                    self.ParentWindow.AddUserType()
-                elif selected == "SDO Server":
-                    self.Manager.AddSDOServerToCurrent()
-                elif selected == "SDO Client":
-                    self.Manager.AddSDOClientToCurrent()
-                elif selected == "PDO Receive":
-                    self.Manager.AddPDOReceiveToCurrent()
-                elif selected == "PDO Transmit":
-                    self.Manager.AddPDOTransmitToCurrent()
-                elif selected == "Map Variable":
-                    self.ParentWindow.AddMapVariable()
+                choice = INDEXCHOICE_OPTIONS_DICT.get(selected, None)
+                if choice is not None:
+                    if INDEXCHOICE_OPTIONS[choice][1] == 0:
+                        getattr(self.ParentWindow, INDEXCHOICE_OPTIONS[choice][2])()
+                    elif INDEXCHOICE_OPTIONS[choice][1] == 1:
+                        getattr(self.Manager, INDEXCHOICE_OPTIONS[choice][2])()
                 elif selected in [menu for menu, indexes in self.Manager.GetCurrentSpecificMenu()]:
                     self.Manager.AddSpecificEntryToCurrent(selected)
                 else:
@@ -548,23 +601,15 @@
                 self.ListIndex.append(index)
             if self.Editable:
                 self.ChoiceIndex = []
-                if i == 0:
-                    self.IndexChoice.Append("User Type")
-                    self.IndexChoice.SetStringSelection("User Type")
-                elif i == 2:
-                    self.IndexChoice.Append("SDO Server")
-                    self.IndexChoice.Append("SDO Client")
-                    if choiceindex != wx.NOT_FOUND and choice == self.IndexChoice.GetString(choiceindex):
-                         self.IndexChoice.SetStringSelection(choice)
-                elif i in (3, 4):
-                    self.IndexChoice.Append("PDO Receive")
-                    self.IndexChoice.SetStringSelection("PDO Receive")
-                elif i in (5, 6):
-                    self.IndexChoice.Append("PDO Transmit")
-                    self.IndexChoice.SetStringSelection("PDO Transmit")
-                elif i == 8:
-                    self.IndexChoice.Append("Map Variable")
-                    self.IndexChoice.SetStringSelection("Map Variable")
+                choices = INDEXCHOICE_SECTIONS.get(i, None)
+                if choices is not None:
+                    for c in choices:
+                        self.IndexChoice.Append(INDEXCHOICE_OPTIONS[c][0])
+                    if len(choices) > 1:
+                        if choiceindex != wx.NOT_FOUND and choice == self.IndexChoice.GetString(choiceindex):
+                            self.IndexChoice.SetStringSelection(choice)
+                    else:
+                        self.IndexChoice.SetSelection(0)
                 else:
                     for name, index in self.Manager.GetCurrentValidChoices(values["minIndex"], values["maxIndex"]):
                         if index:
@@ -759,8 +804,8 @@
                 index = self.ListIndex[selected]
                 if self.Manager.IsCurrentEntry(index):
                     infos = self.Manager.GetEntryInfos(index)
-                    dialog = wx.TextEntryDialog(self, "Give a new name for index 0x%04X"%index,
-                                 "Rename an index", infos["name"], wx.OK|wx.CANCEL)
+                    dialog = wx.TextEntryDialog(self, _("Give a new name for index 0x%04X")%index,
+                                 _("Rename an index"), infos["name"], wx.OK|wx.CANCEL)
                     if dialog.ShowModal() == wx.ID_OK:
                         self.Manager.SetCurrentEntryName(index, dialog.GetValue())
                         self.ParentWindow.RefreshBufferState()
@@ -805,8 +850,8 @@
             if selected != wx.NOT_FOUND:
                 index = self.ListIndex[selected]
                 if self.Manager.IsCurrentEntry(index):
-                    dialog = wx.TextEntryDialog(self, "Number of subindexes to add:",
-                                 "Add subindexes", "1", wx.OK|wx.CANCEL)
+                    dialog = wx.TextEntryDialog(self, _("Number of subindexes to add:"),
+                                 _("Add subindexes"), "1", wx.OK|wx.CANCEL)
                     if dialog.ShowModal() == wx.ID_OK:
                         try:
                             number = int(dialog.GetValue())
@@ -814,7 +859,7 @@
                             self.ParentWindow.RefreshBufferState()
                             self.RefreshIndexList()
                         except:
-                            message = wx.MessageDialog(self, "An integer is required!", "ERROR", wx.OK|wx.ICON_ERROR)
+                            message = wx.MessageDialog(self, _("An integer is required!"), _("ERROR"), wx.OK|wx.ICON_ERROR)
                             message.ShowModal()
                             message.Destroy()
                     dialog.Destroy()
@@ -826,8 +871,8 @@
             if selected != wx.NOT_FOUND:
                 index = self.ListIndex[selected]
                 if self.Manager.IsCurrentEntry(index):
-                    dialog = wx.TextEntryDialog(self, "Number of subindexes to delete:",
-                                 "Delete subindexes", "1", wx.OK|wx.CANCEL)
+                    dialog = wx.TextEntryDialog(self, _("Number of subindexes to delete:"),
+                                 _("Delete subindexes"), "1", wx.OK|wx.CANCEL)
                     if dialog.ShowModal() == wx.ID_OK:
                         try:
                             number = int(dialog.GetValue())
@@ -835,7 +880,7 @@
                             self.ParentWindow.RefreshBufferState()
                             self.RefreshIndexList()
                         except:
-                            message = wx.MessageDialog(self, "An integer is required!", "ERROR", wx.OK|wx.ICON_ERROR)
+                            message = wx.MessageDialog(self, _("An integer is required!"), _("ERROR"), wx.OK|wx.ICON_ERROR)
                             message.ShowModal()
                             message.Destroy()
                     dialog.Destroy()