Hi,

Find attached a first patch that add internationalization support in
Freevo. It's main purpose is to enclose strings between '_(...)' for all
the strings displayed on screen.
For example, the string:
  return 'Directory on disc [%s]' % self.media.label
is replaced by:
  return _('Directory on disc [%s]') % self.media.label

To notice the changes at runtime, you have to set LANG variable to a
supported language (For example, export LANG=fr).

To support internationalization, we have to add a directory 'locale' in
freevo (cf. attached file freevo_locale.tgz). This directory contains
the .mo files that translate english strings in the supported language.
For the moment, only French has a (very) limited support (only
directory.py, main.py, menu.py, osd.py, record_server.py, tv/tv.py, and
tv/tvguide.py were internationalized). I plan to update the other files
in the next days.
If you want to add a new language, you must provide translations for all
the strings in freevo.pot file.

Please note that, for the moment, all the strings read from the XML
files are not translated... I try to find a solution that would prevent
us to have as many version of an xml file as we have different supported
languages.

Regards,

David

Attachment: freevo_locale.tgz
Description: application/compressed-tar

diff -Naur freevo/src/directory.py freevo_new/src/directory.py
--- freevo/src/directory.py	2003-08-21 00:45:11.000000000 -0400
+++ freevo_new/src/directory.py	2003-08-21 00:59:08.000000000 -0400
@@ -265,8 +265,8 @@
         """
         if attr == 'type':
             if self.media:
-                return 'Directory on disc [%s]' % self.media.label
-            return 'Directory'
+                return _('Directory on disc [%s]') % self.media.label
+            return _('Directory')
         return Item.getattr(self, attr)
 
 
@@ -274,20 +274,20 @@
         """
         return a list of actions for this item
         """
-        items = [ ( self.cwd, 'Browse directory' ) ]
+        items = [ ( self.cwd, _('Browse directory') ) ]
 
         # this doen't work right now because we have no playlist
         # at this point :-(
         
         # if self.playlist and len(self.playlist) > 1:
         #     items += [ (RandomPlaylist(self.playlist, self),
-        #                 'Random play all items' ) ]
+        #                 _('Random play all items') ) ]
 
         if ((not self.display_type or self.display_type == 'audio') and
             config.AUDIO_RANDOM_PLAYLIST == 1):
             items += [ (RandomPlaylist((self.dir, config.SUFFIX_AUDIO_FILES),
                                        self),
-                        'Recursive random play all items') ]
+                        _('Recursive random play all items')) ]
         return items
     
 
@@ -310,7 +310,7 @@
             
 	if os.path.isfile(self.dir + '/.password'):
 	    print 'password protected dir'
-	    pb = PasswordInputBox(text='Enter Password', handler=self.pass_cmp_cb)
+	    pb = PasswordInputBox(text=_('Enter Password'), handler=self.pass_cmp_cb)
 	    pb.show()
 	    # save these so the InputBox callback can pass them to do_cwd
 	    self.arg = arg
@@ -335,7 +335,7 @@
 	if word == password:
 	    self.do_cwd(self.arg, self.menuw)
 	else:
-	    pb = AlertBox(text='Password incorrect')
+	    pb = AlertBox(text=_('Password incorrect'))
 	    pb.show()
             return
 
@@ -375,9 +375,9 @@
         pop = None
         if (num_changes > 10) or (num_changes and self.media):
             if self.media:
-                pop = PopupBox(text='Scanning disc, be patient...')
+                pop = PopupBox(text=_('Scanning disc, be patient...'))
             else:
-                pop = PopupBox(text='Scanning directory, be patient...')
+                pop = PopupBox(text=_('Scanning directory, be patient...'))
             pop.show()
 
         if num_changes > 0:
diff -Naur freevo/src/main.py freevo_new/src/main.py
--- freevo/src/main.py	2003-08-21 00:45:12.000000000 -0400
+++ freevo_new/src/main.py	2003-08-21 00:59:10.000000000 -0400
@@ -149,6 +149,21 @@
 from item import Item
 import event as em
 
+# For Internationalization purpose
+# an exception is raised with Python 2.1 if LANG is unavailable.
+import gettext
+if gettext.find('freevo'): # Test if installed in '/usr/share/locale'
+    try:
+      gettext.install('freevo')
+    except:
+      import __builtin__
+      __builtin__.__dict__['_']= lambda m: m
+else:
+    try:
+      gettext.install('freevo', './locale')
+    except: # unavailable, define '_' for all modules
+      import __builtin__
+      __builtin__.__dict__['_']= lambda m: m
 
 skin    = skin.get_singleton()
 
@@ -175,7 +190,7 @@
     import plugin
 
     osd.clearscreen(color=osd.COL_BLACK)
-    osd.drawstring('shutting down...', osd.width/2 - 90, osd.height/2 - 10,
+    osd.drawstring(_('shutting down...'), osd.width/2 - 90, osd.height/2 - 10,
                    fgcolor=osd.COL_ORANGE, bgcolor=osd.COL_BLACK)
     osd.update()
 
@@ -273,7 +288,7 @@
         
         items = get_main_menu(self)
 
-        mainmenu = menu.Menu('FREEVO MAIN MENU', items, item_types='main', umount_all = 1)
+        mainmenu = menu.Menu(_('FREEVO MAIN MENU'), items, item_types='main', umount_all = 1)
         menuwidget.pushmenu(mainmenu)
         osd.add_app(menuwidget)
 
diff -Naur freevo/src/menu.py freevo_new/src/menu.py
--- freevo/src/menu.py	2003-08-21 00:45:12.000000000 -0400
+++ freevo_new/src/menu.py	2003-08-21 00:59:10.000000000 -0400
@@ -527,7 +527,7 @@
                     
             if action == None:
                 print 'No action.. '
-                AlertBox(text='No action defined for this choice!').show()
+                AlertBox(text=_('No action defined for this choice!')).show()
             else:
                 action( arg=arg, menuw=self )
             return
diff -Naur freevo/src/osd.py freevo_new/src/osd.py
--- freevo/src/osd.py	2003-08-21 00:45:12.000000000 -0400
+++ freevo_new/src/osd.py	2003-08-21 00:59:11.000000000 -0400
@@ -383,11 +383,11 @@
         if config.CONF.display == 'x11' and config.START_FULLSCREEN_X == 1:
             self.toggle_fullscreen()
 
-        help = ['z = Toggle Fullscreen']
-        help += ['Arrow Keys = Move']
-        help += ['Spacebar = Select']
-        help += ['Escape = Stop/Prev. Menu']
-        help += ['h = Help']
+        help = [_('z = Toggle Fullscreen')]
+        help += [_('Arrow Keys = Move')]
+        help += [_('Spacebar = Select')]
+        help += [_('Escape = Stop/Prev. Menu')]
+        help += [_('h = Help')]
         help_str = '    '.join(help)
         pygame.display.set_caption('Freevo' + ' '*7 + help_str)
         icon = pygame.image.load(os.path.join(config.ICON_DIR,
diff -Naur freevo/src/record_server.py freevo_new/src/record_server.py
--- freevo/src/record_server.py	2003-08-21 00:45:14.000000000 -0400
+++ freevo_new/src/record_server.py	2003-08-21 00:59:12.000000000 -0400
@@ -177,10 +177,10 @@
         global guide
 
         if not prog:
-            return (FALSE, 'no prog')
+            return (FALSE, _('no prog'))
     
         if prog.stop < time.time():
-            return (FALSE, 'cannot record it if it is over')
+            return (FALSE, _('cannot record it if it is over'))
             
         self.updateGuide()
     
@@ -193,33 +193,33 @@
         scheduledRecordings.addProgram(prog, tv_util.getKey(prog))
         self.saveScheduledRecordings(scheduledRecordings)
        
-        return (TRUE, 'recording scheduled')
+        return (TRUE, _('recording scheduled'))
     
 
     def removeScheduledRecording(self, prog=None):
         if not prog:
-            return (FALSE, 'no prog')
+            return (FALSE, _('no prog'))
 
         scheduledRecordings = self.getScheduledRecordings()
         scheduledRecordings.removeProgram(prog, tv_util.getKey(prog))
         self.saveScheduledRecordings(scheduledRecordings)
        
-        return (TRUE, 'recording removed')
+        return (TRUE, _('recording removed'))
    
 
     def isProgScheduled(self, prog, schedule=None):
     
         if schedule == {}:
-            return (FALSE, 'prog not scheduled')
+            return (FALSE, _('prog not scheduled'))
 
         if not schedule:
             schedule = self.getScheduledRecordings().getProgramList()
 
         for me in schedule.values():
             if me.start == prog.start and me.channel_id == prog.channel_id:
-                return (TRUE, 'prog is scheduled')
+                return (TRUE, _('prog is scheduled'))
 
-        return (FALSE, 'prog not scheduled')
+        return (FALSE, _('prog not scheduled'))
 
 
     def findProg(self, chan=None, start=None):
@@ -228,7 +228,7 @@
         log.debug('findProg: %s, %s' % (chan, start))
 
         if not chan or not start:
-            return (FALSE, 'no chan or no start')
+            return (FALSE, _('no chan or no start'))
 
         self.updateGuide()
 
@@ -240,7 +240,7 @@
                         log.debug('PROGRAM MATCH')
                         return (TRUE, prog)
 
-        return (FALSE, 'prog not found')
+        return (FALSE, _('prog not found'))
 
 
     def findMatches(self, find=None):
@@ -271,7 +271,7 @@
         if matches:
             return (TRUE, matches)
         else:
-            return (FALSE, 'no matches')
+            return (FALSE, _('no matches'))
 
 
     def updateGuide(self):
@@ -334,7 +334,7 @@
 
     def addFavorite(self, name, prog, exactchan=FALSE, exactdow=FALSE, exacttod=FALSE):
         if not name:
-            return (FALSE, 'no name')
+            return (FALSE, '_(no name'))
     
         (status, favs) = self.getFavorites()
         priority = len(favs) + 1
@@ -345,7 +345,7 @@
         self.saveScheduledRecordings(scheduledRecordings)
         self.addFavoriteToSchedule(fav)
 
-        return (TRUE, 'favorite added')
+        return (TRUE, _('favorite added'))
     
     
     def addEditedFavorite(self, name, title, chan, dow, mod, priority):
@@ -363,12 +363,12 @@
         self.saveScheduledRecordings(scheduledRecordings)
         self.addFavoriteToSchedule(fav)
 
-        return (TRUE, 'favorite added')
+        return (TRUE, _('favorite added'))
     
     
     def removeFavorite(self, name=None):
         if not name:
-            return (FALSE, 'no name')
+            return (FALSE, _('no name'))
        
         (status, fav) = self.getFavorite(name)
         self.removeFavoriteFromSchedule(fav)
@@ -376,7 +376,7 @@
         scheduledRecordings.removeFavorite(name)
         self.saveScheduledRecordings(scheduledRecordings)
 
-        return (TRUE, 'favorite removed')
+        return (TRUE, _('favorite removed'))
        
     
     def clearFavorites(self):
@@ -384,7 +384,7 @@
         scheduledRecordings.clearFavorites()
         self.saveScheduledRecordings(scheduledRecordings)
 
-        return (TRUE, 'favorites cleared')
+        return (TRUE, _('favorites cleared'))
     
     
     def getFavorites(self):
@@ -398,7 +398,7 @@
             fav = favs[name] 
             return (TRUE, fav)
         else:
-            return (FALSE, 'not a favorite')
+            return (FALSE, _('not a favorite'))
     
     
     def adjustPriority(self, favname, mod=0):
@@ -440,7 +440,7 @@
         sr.setFavoritesList(favs)
         self.saveScheduledRecordings(sr)
 
-        return (TRUE, 'priorities adjusted')
+        return (TRUE, _('priorities adjusted'))
     
     
     def isProgAFavorite(self, prog, favs=None):
@@ -465,7 +465,7 @@
                             return (TRUE, fav.name)
     
         # if we get this far prog is not a favorite
-        return (FALSE, 'not a favorite')
+        return (FALSE, _('not a favorite'))
     
     
     def removeFavoriteFromSchedule(self, fav):
@@ -482,7 +482,7 @@
             if isFav:
                 self.removeScheduledRecording(prog)
 
-        return (TRUE, 'favorite unscheduled')
+        return (TRUE, _('favorite unscheduled'))
     
     
     def addFavoriteToSchedule(self, fav):
@@ -499,7 +499,7 @@
                     prog.isFavorite = favorite
                     self.scheduleRecording(prog)
 
-        return (TRUE, 'favorite scheduled')
+        return (TRUE, _('favorite scheduled'))
     
     
     def updateFavoritesSchedule(self):
@@ -521,7 +521,7 @@
         (status, favs) = self.getFavorites()
 
         if not len(favs):
-            return (FALSE, 'there are no favorites to update')
+            return (FALSE, _('there are no favorites to update'))
        
     
         # Then remove all scheduled favorites in that timeframe to
@@ -546,7 +546,7 @@
                     prog.isFavorite = favorite
                     self.scheduleRecording(prog)
 
-        return (TRUE, 'favorites schedule updated')
+        return (TRUE, _('favorites schedule updated'))
     
 
     #################################################################
diff -Naur freevo/src/tv/tv.py freevo_new/src/tv/tv.py
--- freevo/src/tv/tv.py	2003-08-21 00:45:28.000000000 -0400
+++ freevo_new/src/tv/tv.py	2003-08-21 00:59:13.000000000 -0400
@@ -115,14 +115,14 @@
         if tv_channel_id == channel_id:
             return tv_tuner_id
 
-    AlertBox(text='Could not find TV channel %s' % channel_id).show()
+    AlertBox(text=_('Could not find TV channel')+' %s' % channel_id).show()
     return None
 
 def get_friendly_channel(channel_id):
     channel_name = tv_util.get_chan_displayname(channel_id)
 
     if not channel_name: 
-        AlertBox(text='Could not find TV channel %s' % channel_id).show()
+        AlertBox(text=_('Could not find TV channel')+' %s' % channel_id).show()
 
     return channel_name
 
@@ -145,11 +145,11 @@
 
 
     def main_menu(self, arg, menuw):
-        items = [ menu.MenuItem('TV Guide', action=self.start_tvguide),
-                  DirItem(config.DIR_RECORD, None, name = 'Recorded Shows',
+        items = [ menu.MenuItem(_('TV Guide'), action=self.start_tvguide),
+                  DirItem(config.DIR_RECORD, None, name = _('Recorded Shows'),
                           display_type='tv'),
-                  menu.MenuItem('Scheduled Recordings',action=self.view_schedule)       ]
-        menuw.pushmenu(menu.Menu('TV MAIN MENU', items, item_types = 'tv'))
+                  menu.MenuItem(_('Scheduled Recordings'),action=self.view_schedule)       ]
+        menuw.pushmenu(menu.Menu(_('TV MAIN MENU'), items, item_types = 'tv'))
 
 
     def get_start_time(self):
@@ -173,8 +173,8 @@
 
         # Check that the TV channel list is not None
         if not config.TV_CHANNELS:
-            msg = 'The list of TV channels is invalid!\n'
-            msg += 'Please check the config file.'
+            msg = _('The list of TV channels is invalid!')+'\n'
+            msg += _('Please check the config file.')
             AlertBox(text=msg).show()
             return
 
@@ -182,7 +182,7 @@
             start_tv(None, ('record', None))
             return
 
-        guide = epg.get_guide(PopupBox(text='Preparing the program guide'))
+        guide = epg.get_guide(PopupBox(text=_('Preparing the program guide')))
 
         start_time = self.get_start_time()
         stop_time = self.get_start_time() + config.TVGUIDE_HOURS_PER_PAGE * 60 * 60
@@ -190,7 +190,7 @@
         channels = guide.GetPrograms(start=start_time+1, stop=stop_time-1)
 
         if not channels:
-            AlertBox(text='TV Guide is corrupt!').show()
+            AlertBox(text=_('TV Guide is corrupt!')).show()
             return
 
         prg = None
diff -Naur freevo/src/tv/tvguide.py freevo_new/src/tv/tvguide.py
--- freevo/src/tv/tvguide.py	2003-08-21 00:45:28.000000000 -0400
+++ freevo_new/src/tv/tvguide.py	2003-08-21 00:59:14.000000000 -0400
@@ -71,12 +71,11 @@
 
 skin = skin.get_singleton() # Create the Skin object
 
-
 TRUE = 1
 FALSE = 0
 
 
-CHAN_NO_DATA = 'This channel has no data loaded'
+CHAN_NO_DATA = _('This channel has no data loaded')
 
 
 class TVGuide(gui.GUIObject):
@@ -432,9 +431,9 @@
             prg.channel_id = channel.id            
             prg.start = 0
             prg.stop = 2147483647   # Year 2038
-            prg.title = 'This channel has no data loaded'
+            prg.title = _('This channel has no data loaded')
             prg.desc = ''
-            to_info = 'This channel has no data loaded'
+            to_info = _('This channel has no data loaded')
 
             
         self.rebuild(start_time, stop_time, start_channel, prg)

Reply via email to