Add i18n to mussorgsky
authorIvan Frade <ivan.frade@nokia.com>
Thu, 22 Apr 2010 14:29:31 +0000 (17:29 +0300)
committerIvan Frade <ivan.frade@nokia.com>
Thu, 22 Apr 2010 14:29:31 +0000 (17:29 +0300)
msgfmt.py [new file with mode: 0644]
po/es.po [new file with mode: 0644]
po/mussorgsky.pot [new file with mode: 0644]
setup.py
src/aa_selection_dialog.py
src/album_art_panel.py
src/browse_panel.py
src/edit_panel_tm.py
src/i18n.py [new file with mode: 0644]
src/mussorgsky.py

diff --git a/msgfmt.py b/msgfmt.py
new file mode 100644 (file)
index 0000000..9d7ca13
--- /dev/null
+++ b/msgfmt.py
@@ -0,0 +1,219 @@
+# -*- coding: utf-8 -*-
+# Written by Martin v. Lwis <loewis@informatik.hu-berlin.de>
+# Plural forms support added by alexander smishlajev <alex@tycobka.lv>
+"""
+Generate binary message catalog from textual translation description.
+
+This program converts a textual Uniforum-style message catalog (.po file) into
+a binary GNU catalog (.mo file).  This is essentially the same function as the
+GNU msgfmt program, however, it is a simpler implementation.
+
+Usage: msgfmt.py [OPTIONS] filename.po
+
+Options:
+    -o file
+    --output-file=file
+        Specify the output file to write to.  If omitted, output will go to a
+        file named filename.mo (based off the input file name).
+
+    -h
+    --help
+        Print this message and exit.
+
+    -V
+    --version
+        Display version information and exit.
+"""
+
+import sys
+import os
+import getopt
+import struct
+import array
+
+__version__ = "1.1"
+
+MESSAGES = {}
+
+
+def usage (ecode, msg=''):
+    """
+    Print usage and msg and exit with given code.
+    """
+    print >> sys.stderr, __doc__
+    if msg:
+        print >> sys.stderr, msg
+    sys.exit(ecode)
+
+
+def add (msgid, transtr, fuzzy):
+    """
+    Add a non-fuzzy translation to the dictionary.
+    """
+    global MESSAGES
+    if not fuzzy and transtr and not transtr.startswith('\0'):
+        MESSAGES[msgid] = transtr
+
+
+def generate ():
+    """
+    Return the generated output.
+    """
+    global MESSAGES
+    keys = MESSAGES.keys()
+    # the keys are sorted in the .mo file
+    keys.sort()
+    offsets = []
+    ids = strs = ''
+    for _id in keys:
+        # For each string, we need size and file offset.  Each string is NUL
+        # terminated; the NUL does not count into the size.
+        offsets.append((len(ids), len(_id), len(strs), len(MESSAGES[_id])))
+        ids += _id + '\0'
+        strs += MESSAGES[_id] + '\0'
+    output = ''
+    # The header is 7 32-bit unsigned integers.  We don't use hash tables, so
+    # the keys start right after the index tables.
+    # translated string.
+    keystart = 7*4+16*len(keys)
+    # and the values start after the keys
+    valuestart = keystart + len(ids)
+    koffsets = []
+    voffsets = []
+    # The string table first has the list of keys, then the list of values.
+    # Each entry has first the size of the string, then the file offset.
+    for o1, l1, o2, l2 in offsets:
+        koffsets += [l1, o1+keystart]
+        voffsets += [l2, o2+valuestart]
+    offsets = koffsets + voffsets
+    output = struct.pack("Iiiiiii",
+                         0x950412deL,       # Magic
+                         0,                 # Version
+                         len(keys),         # # of entries
+                         7*4,               # start of key index
+                         7*4+len(keys)*8,   # start of value index
+                         0, 0)              # size and offset of hash table
+    output += array.array("i", offsets).tostring()
+    output += ids
+    output += strs
+    return output
+
+
+def make (filename, outfile):
+    ID = 1
+    STR = 2
+    global MESSAGES
+    MESSAGES = {}
+
+    # Compute .mo name from .po name and arguments
+    if filename.endswith('.po'):
+        infile = filename
+    else:
+        infile = filename + '.po'
+    if outfile is None:
+        outfile = os.path.splitext(infile)[0] + '.mo'
+
+    try:
+        lines = open(infile).readlines()
+    except IOError, msg:
+        print >> sys.stderr, msg
+        sys.exit(1)
+
+    section = None
+    fuzzy = 0
+
+    # Parse the catalog
+    msgid = msgstr = ''
+    lno = 0
+    for l in lines:
+        lno += 1
+        # If we get a comment line after a msgstr, this is a new entry
+        if l[0] == '#' and section == STR:
+            add(msgid, msgstr, fuzzy)
+            section = None
+            fuzzy = 0
+        # Record a fuzzy mark
+        if l[:2] == '#,' and (l.find('fuzzy') >= 0):
+            fuzzy = 1
+        # Skip comments
+        if l[0] == '#':
+            continue
+        # Start of msgid_plural section, separate from singular form with \0
+        if l.startswith('msgid_plural'):
+            msgid += '\0'
+            l = l[12:]
+        # Now we are in a msgid section, output previous section
+        elif l.startswith('msgid'):
+            if section == STR:
+                add(msgid, msgstr, fuzzy)
+            section = ID
+            l = l[5:]
+            msgid = msgstr = ''
+        # Now we are in a msgstr section
+        elif l.startswith('msgstr'):
+            section = STR
+            l = l[6:]
+            # Check for plural forms
+            if l.startswith('['):
+                # Separate plural forms with \0
+                if not l.startswith('[0]'):
+                    msgstr += '\0'
+                # Ignore the index - must come in sequence
+                l = l[l.index(']') + 1:]
+        # Skip empty lines
+        l = l.strip()
+        if not l:
+            continue
+        # XXX: Does this always follow Python escape semantics?
+        l = eval(l)
+        if section == ID:
+            msgid += l
+        elif section == STR:
+            msgstr += l
+        else:
+            print >> sys.stderr, 'Syntax error on %s:%d' % (infile, lno), \
+                  'before:'
+            print >> sys.stderr, l
+            sys.exit(1)
+    # Add last entry
+    if section == STR:
+        add(msgid, msgstr, fuzzy)
+
+    # Compute output
+    output = generate()
+
+    try:
+        open(outfile,"wb").write(output)
+    except IOError,msg:
+        print >> sys.stderr, msg
+
+
+def main ():
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], 'hVo:',
+                                   ['help', 'version', 'output-file='])
+    except getopt.error, msg:
+        usage(1, msg)
+
+    outfile = None
+    # parse options
+    for opt, arg in opts:
+        if opt in ('-h', '--help'):
+            usage(0)
+        elif opt in ('-V', '--version'):
+            print >> sys.stderr, "msgfmt.py", __version__
+            sys.exit(0)
+        elif opt in ('-o', '--output-file'):
+            outfile = arg
+    # do it
+    if not args:
+        print >> sys.stderr, 'No input file given'
+        print >> sys.stderr, "Try `msgfmt --help' for more information."
+        return
+
+    for filename in args:
+        make(filename, outfile)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/po/es.po b/po/es.po
new file mode 100644 (file)
index 0000000..2adadee
--- /dev/null
+++ b/po/es.po
@@ -0,0 +1,91 @@
+# Spanish translations for PACKAGE package.
+# Copyright (C) 2010 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# ivan <ivan.frade@nokia.com>, 2010.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-04-22 16:50+0300\n"
+"PO-Revision-Date: 2010-04-22 16:50+0300\n"
+"Last-Translator: ivan frade <ivan.frade@gmail.com>\n"
+"Language-Team: Spanish\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ASCII\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: debian/mussorgsky/usr/lib/mussorgsky/edit_panel_tm.py:50
+#: src/edit_panel_tm.py:50
+msgid "Edit song"
+msgstr "Editar cancion"
+
+#: debian/mussorgsky/usr/lib/mussorgsky/edit_panel_tm.py:201
+#: src/edit_panel_tm.py:201
+msgid "Title:"
+msgstr "Titulo:"
+
+#: debian/mussorgsky/usr/lib/mussorgsky/edit_panel_tm.py:209
+#: src/edit_panel_tm.py:209
+msgid "Artist:"
+msgstr "Artista:"
+
+#: debian/mussorgsky/usr/lib/mussorgsky/edit_panel_tm.py:217
+#: src/edit_panel_tm.py:217
+msgid "Album:"
+msgstr "Disco:"
+
+#: debian/mussorgsky/usr/lib/mussorgsky/album_art_panel.py:21
+#: src/album_art_panel.py:21
+msgid "Album art selection"
+msgstr "Seleccion de portada"
+
+#: debian/mussorgsky/usr/lib/mussorgsky/album_art_panel.py:60
+#: src/album_art_panel.py:60
+msgid "Automatic download"
+msgstr "Descarga automatica"
+
+#: debian/mussorgsky/usr/lib/mussorgsky/mussorgsky.py:57 src/mussorgsky.py:57
+msgid "Metadata"
+msgstr "Metadatos"
+
+#: debian/mussorgsky/usr/lib/mussorgsky/mussorgsky.py:63 src/mussorgsky.py:63
+msgid "Album art"
+msgstr "Portadas"
+
+#: debian/mussorgsky/usr/lib/mussorgsky/browse_panel.py:28
+#: debian/mussorgsky/usr/lib/mussorgsky/browse_panel.py:140
+#: src/browse_panel.py:28 src/browse_panel.py:140
+msgid "All music"
+msgstr "Todas las canciones"
+
+#: debian/mussorgsky/usr/lib/mussorgsky/browse_panel.py:63
+#: src/browse_panel.py:63
+msgid "All"
+msgstr "Todas"
+
+#: debian/mussorgsky/usr/lib/mussorgsky/browse_panel.py:67
+#: src/browse_panel.py:67
+msgid "Incomplete"
+msgstr "Incompletas"
+
+#: debian/mussorgsky/usr/lib/mussorgsky/browse_panel.py:142
+#: src/browse_panel.py:142
+msgid "Music with uncomplete metadata"
+msgstr "Music con datos incompletos"
+
+#: debian/mussorgsky/usr/lib/mussorgsky/browse_panel.py:144
+#: src/browse_panel.py:144
+msgid "Search results"
+msgstr "Resultados"
+
+#: debian/mussorgsky/usr/lib/mussorgsky/aa_selection_dialog.py:57
+#: src/aa_selection_dialog.py:57
+msgid "Select album art"
+msgstr "Seleccione portada"
+
+#: debian/mussorgsky/usr/lib/mussorgsky/aa_selection_dialog.py:95
+#: src/aa_selection_dialog.py:95
+msgid "New search:"
+msgstr "Nueva busqueda:"
diff --git a/po/mussorgsky.pot b/po/mussorgsky.pot
new file mode 100644 (file)
index 0000000..173d4b1
--- /dev/null
@@ -0,0 +1,91 @@
+# 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: 2010-04-22 16:50+0300\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"
+
+#: debian/mussorgsky/usr/lib/mussorgsky/edit_panel_tm.py:50
+#: src/edit_panel_tm.py:50
+msgid "Edit song"
+msgstr ""
+
+#: debian/mussorgsky/usr/lib/mussorgsky/edit_panel_tm.py:201
+#: src/edit_panel_tm.py:201
+msgid "Title:"
+msgstr ""
+
+#: debian/mussorgsky/usr/lib/mussorgsky/edit_panel_tm.py:209
+#: src/edit_panel_tm.py:209
+msgid "Artist:"
+msgstr ""
+
+#: debian/mussorgsky/usr/lib/mussorgsky/edit_panel_tm.py:217
+#: src/edit_panel_tm.py:217
+msgid "Album:"
+msgstr ""
+
+#: debian/mussorgsky/usr/lib/mussorgsky/album_art_panel.py:21
+#: src/album_art_panel.py:21
+msgid "Album art selection"
+msgstr ""
+
+#: debian/mussorgsky/usr/lib/mussorgsky/album_art_panel.py:60
+#: src/album_art_panel.py:60
+msgid "Automatic download"
+msgstr ""
+
+#: debian/mussorgsky/usr/lib/mussorgsky/mussorgsky.py:57 src/mussorgsky.py:57
+msgid "Metadata"
+msgstr ""
+
+#: debian/mussorgsky/usr/lib/mussorgsky/mussorgsky.py:63 src/mussorgsky.py:63
+msgid "Album art"
+msgstr ""
+
+#: debian/mussorgsky/usr/lib/mussorgsky/browse_panel.py:28
+#: debian/mussorgsky/usr/lib/mussorgsky/browse_panel.py:140
+#: src/browse_panel.py:28 src/browse_panel.py:140
+msgid "All music"
+msgstr ""
+
+#: debian/mussorgsky/usr/lib/mussorgsky/browse_panel.py:63
+#: src/browse_panel.py:63
+msgid "All"
+msgstr ""
+
+#: debian/mussorgsky/usr/lib/mussorgsky/browse_panel.py:67
+#: src/browse_panel.py:67
+msgid "Incomplete"
+msgstr ""
+
+#: debian/mussorgsky/usr/lib/mussorgsky/browse_panel.py:142
+#: src/browse_panel.py:142
+msgid "Music with uncomplete metadata"
+msgstr ""
+
+#: debian/mussorgsky/usr/lib/mussorgsky/browse_panel.py:144
+#: src/browse_panel.py:144
+msgid "Search results"
+msgstr ""
+
+#: debian/mussorgsky/usr/lib/mussorgsky/aa_selection_dialog.py:57
+#: src/aa_selection_dialog.py:57
+msgid "Select album art"
+msgstr ""
+
+#: debian/mussorgsky/usr/lib/mussorgsky/aa_selection_dialog.py:95
+#: src/aa_selection_dialog.py:95
+msgid "New search:"
+msgstr ""
index 34e39ed..0bc3bc7 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -1,9 +1,64 @@
 #!/usr/bin/env python2.5
  
 from distutils.core import setup
+from distutils.core import setup
+from distutils import cmd
+#from distutils.command.install import install as _install
+from distutils.command.install_data import install_data as _install_data
+from distutils.command.build import build as _build
 
+import msgfmt
 import os
 
+class build_trans(cmd.Command):
+    description = 'Compile .po files into .mo files'
+    def initialize_options(self):
+        pass
+
+    def finalize_options(self):
+        pass
+
+    def run(self):
+        po_dir = os.path.join(os.path.dirname(os.curdir), 'po')
+        for path, names, filenames in os.walk(po_dir):
+            for f in filenames:
+                if f.endswith('.po'):
+                    lang = f[:len(f) - 3]
+                    src = os.path.join(path, f)
+                    dest_path = os.path.join('build', 'locale', lang, 'LC_MESSAGES')
+                    dest = os.path.join(dest_path, 'mussorgsky.mo')
+                    if not os.path.exists(dest_path):
+                        os.makedirs(dest_path)
+                    if not os.path.exists(dest):
+                        print 'Compiling %s' % src
+                        msgfmt.make(src, dest)
+                    else:
+                        src_mtime = os.stat(src)[8]
+                        dest_mtime = os.stat(dest)[8]
+                        if src_mtime > dest_mtime:
+                            print 'Compiling %s' % src
+                            msgfmt.make(src, dest)
+
+class build(_build):
+    sub_commands = _build.sub_commands + [('build_trans', None)]
+    def run(self):
+        _build.run(self)
+
+class install_data(_install_data):
+
+    def run(self):
+        for lang in os.listdir('build/locale/'):
+            lang_dir = os.path.join('share', 'locale', lang, 'LC_MESSAGES')
+            lang_file = os.path.join('build', 'locale', lang, 'LC_MESSAGES', 'mussorgsky.mo')
+            self.data_files.append( (lang_dir, [lang_file]) )
+        _install_data.run(self)
+
+cmdclass = {
+    'build': build,
+    'build_trans': build_trans,
+    'install_data': install_data,
+}
+
 SCRIPTS=  ['data/mussorgsky']
 
 DATA = [('share/applications/hildon', ['data/mussorgsky.desktop']),
@@ -21,7 +76,8 @@ DATA = [('share/applications/hildon', ['data/mussorgsky.desktop']),
                             'src/mutagen_backend.py',                            
                             'src/player_backend.py',
                             'src/tracker_backend.py',
-                            'src/utils.py'])]
+                            'src/utils.py',
+                            'src/i18n.py'])]
  
 setup(name         = 'mussorgsky',
       version      = '0.4',
@@ -31,5 +87,6 @@ setup(name         = 'mussorgsky',
       url          = 'http://mussorgsky.garage.maemo.org',
       license      = 'GPL v2 or later',
       data_files   = DATA,
-      scripts      = SCRIPTS
+      scripts      = SCRIPTS,
+      cmdclass     = cmdclass
       )
index b055d2d..58892c6 100644 (file)
@@ -5,6 +5,9 @@ from album_art_thread import MussorgskyAlbumArt
 
 RESPONSE_CLICK = 1
 
+import i18n
+_ = i18n.language.gettext
+
 class ClickableImage (gtk.EventBox):
 
     def __init__ (self, isRemoveOption=False):
@@ -51,7 +54,7 @@ class AlbumArtSelectionDialog (gtk.Dialog):
         Optionally downloader (for testing porpouses)
         """
         gtk.Dialog.__init__ (self,
-                             "Select album art", parent,
+                             _("Select album art"), parent,
                              gtk.DIALOG_DESTROY_WITH_PARENT,
                              (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT))
         self.artist = artist
@@ -89,7 +92,7 @@ class AlbumArtSelectionDialog (gtk.Dialog):
         hbox.pack_start (image, expand=False, fill=True)
         self.vbox.pack_start (hbox, padding=24)
         
-        label = gtk.Label ("New search:")
+        label = gtk.Label (_("New search:"))
         self.entry = hildon.Entry (gtk.HILDON_SIZE_FINGER_HEIGHT)
         self.entry.set_text (self.artist + " " +  self.album)
 
index 005b9a5..96b6758 100644 (file)
@@ -11,25 +11,24 @@ import time
 
 EMPTY_PIXBUF = gtk.gdk.Pixbuf (gtk.gdk.COLORSPACE_RGB, False, 8, 64, 64)
 
+import i18n
+_ = i18n.language.gettext
+
 class MussorgskyAlbumArtPanel (hildon.StackableWindow):
 
     def __init__ (self, album_artists):
         hildon.StackableWindow.__init__ (self)
-        self.set_title ("Album art handling")
+        self.set_title (_("Album art selection"))
         self.set_border_width (12)
-        print "Create view       :",time.time ()
         self.__create_view ()
-        print "Create view (DONE):", time.time ()
         self.downloader = None
         # Visible string, image, artist, album, painted!
         self.model = gtk.ListStore (str, gtk.gdk.Pixbuf, str, str, bool)
-        print "Populate model      :", time.time ()
         for p in album_artists:
             if (not p[0]):
                 continue
             t = (None, None, p[1], p[0], False)
             self.model.append (t)
-        print "Populate model (DONE):", time.time ()
             
         self.treeview.set_model (self.model)
 
@@ -58,7 +57,7 @@ class MussorgskyAlbumArtPanel (hildon.StackableWindow):
         menu = hildon.AppMenu ()
         automatic_retrieval = hildon.Button (hildon.BUTTON_STYLE_NORMAL,
                                              hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
-        automatic_retrieval.set_title ("Automatic retrieval")
+        automatic_retrieval.set_title (_("Automatic download"))
         automatic_retrieval.connect ("clicked", self.get_all_album_art)
         menu.append (automatic_retrieval)
         menu.show_all ()
@@ -68,7 +67,6 @@ class MussorgskyAlbumArtPanel (hildon.StackableWindow):
         text, pixbuf, artist, album, not_first_time = model.get (iter, 0, 1, 2, 3, 4)
         if (not_first_time):
             if (text == None):
-                print "Setting text", album
                 text = "".join (["<b>", escape_html (album),"</b>\n<small>",
                                  escape_html(artist), "</small>"])
                 model.set (iter, 0, text)
index 233a78e..1a97bec 100755 (executable)
@@ -18,12 +18,14 @@ SHOW_UNCOMPLETE = 2
 SHOW_MATCH = 3
 
 import time
+import i18n
+_ = i18n.language.gettext
 
 class MussorgskyBrowsePanel (hildon.StackableWindow):
 
     def __init__ (self, songs_list):
         hildon.StackableWindow.__init__ (self)
-        self.set_title ("Browse collection")
+        self.set_title (_("All music"))
         self.set_border_width (12)
         self.__create_view ()
         
@@ -58,11 +60,11 @@ class MussorgskyBrowsePanel (hildon.StackableWindow):
         vbox = gtk.VBox (homogeneous=False)
 
         menu = hildon.AppMenu ()
-        self.all_items = gtk.RadioButton (None, "All")
+        self.all_items = gtk.RadioButton (None, _("All"))
         self.all_items.set_mode (False)
         self.all_items.connect_after ("toggled", self.__set_filter_mode, SHOW_ALL)
         menu.add_filter (self.all_items)
-        self.broken_items = gtk.RadioButton (self.all_items, "Uncomplete")
+        self.broken_items = gtk.RadioButton (self.all_items, _("Incomplete"))
         self.broken_items.set_mode (False)
         self.broken_items.connect_after ("toggled",
                                          self.__set_filter_mode, SHOW_UNCOMPLETE)
@@ -133,6 +135,15 @@ class MussorgskyBrowsePanel (hildon.StackableWindow):
         edit_view.set_model (self.treeview.get_model (), self.treeview.get_model ().get_iter (path))
         edit_view.show_all ()
 
+    def __update_title_with_filter (self, filter_mode):
+        if self.filter_mode == SHOW_ALL:
+            self.set_title (_("All music"))
+        elif self.filter_mode == SHOW_UNCOMPLETE:
+            self.set_title (_("Music with uncomplete metadata"))
+        elif self.filter_mode == SHOW_MATCH:
+            self.set_title (_("Search results"))
+        
+
     def __set_filter_mode (self, button, filter_mode):
         """
         Parameter to use it as callback as well as regular function
@@ -141,13 +152,10 @@ class MussorgskyBrowsePanel (hildon.StackableWindow):
             # Don't refilter if there is no change!
             return
         self.filter_mode = filter_mode
-
-        start = time.time ()
+        self.__update_title_with_filter (self.filter_mode)
         self.treeview.set_model (None)
         self.filtered_model.refilter ()
         self.treeview.set_model (self.filtered_model)
-        end = time.time ()
-        print "Refiltering ", end - start
 
     def filter_entry (self, model, it):
         if self.filter_mode == SHOW_ALL:
@@ -187,7 +195,7 @@ if __name__ == "__main__":
               "Artist%d" % i,
               get_some_empty_titles (i),
               "album <%d>" % i,
-              "audio/mpeg") for i in range (0, 30000)]
+              "audio/non-supported") for i in range (0, 100)]
 
     songs.append (("file:///no/metadata/at/all",
                    "music",
index 47e9807..751c534 100644 (file)
@@ -19,6 +19,9 @@ SEARCH_COLUMN = 7
 
 THEME_PATH = "/usr/share/themes/default"
 
+import i18n
+_ = i18n.language.gettext
+
 class MussorgskyEditPanel (hildon.StackableWindow):
 
     def __init__ (self):
@@ -44,8 +47,8 @@ class MussorgskyEditPanel (hildon.StackableWindow):
 
         
     def update_title (self):
-        self.set_title ("Edit (%d/%d)" % (self.model.get_path (self.current)[0] + 1,
-                                          len (self.model)))
+        self.set_title (_("Edit song") + " (%d/%d)" % (self.model.get_path (self.current)[0] + 1,
+                                                       len (self.model)))
 
     def get_current_row (self):
         if (not self.current):
@@ -152,8 +155,8 @@ class MussorgskyEditPanel (hildon.StackableWindow):
                UI_COLUMN, text,
                SEARCH_COLUMN, search_str)
         try:
-            self.writer.save_metadata_on_file (uri,#new_song[URI_COLUMN],
-                                               mime, #new_song[MIME_COLUMN],
+            self.writer.save_metadata_on_file (uri,
+                                               mime, 
                                                self.artist_button.get_value (),
                                                self.title_entry.get_text (),
                                                self.album_button.get_value ())
@@ -195,7 +198,7 @@ class MussorgskyEditPanel (hildon.StackableWindow):
         view_vbox.pack_start (central_panel, expand=True, fill=True)
 
         # Title row
-        label_title = gtk.Label ("Title:")
+        label_title = gtk.Label (_("Title:"))
         table.attach (label_title, 0, 1, 0, 1, 0)
         self.title_entry = hildon.Entry(gtk.HILDON_SIZE_FINGER_HEIGHT)
         table.attach (self.title_entry, 1, 2, 0, 1)
@@ -203,7 +206,7 @@ class MussorgskyEditPanel (hildon.StackableWindow):
         # Artist row
         self.artist_button = hildon.PickerButton (gtk.HILDON_SIZE_THUMB_HEIGHT,
                                                   hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
-        self.artist_button.set_title ("Artist: ")
+        self.artist_button.set_title (_("Artist:"))
         # Set data will set the selector
         table.attach (self.artist_button, 0, 2, 1, 2)
 
@@ -211,7 +214,7 @@ class MussorgskyEditPanel (hildon.StackableWindow):
         # Album row
         self.album_button = hildon.PickerButton (gtk.HILDON_SIZE_THUMB_HEIGHT,
                                                  hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
-        self.album_button.set_title ("Album: ")
+        self.album_button.set_title (_("Album:"))
         # set_data will set the selector
         table.attach (self.album_button, 0, 2, 2, 3)
         
diff --git a/src/i18n.py b/src/i18n.py
new file mode 100644 (file)
index 0000000..4b5ae83
--- /dev/null
@@ -0,0 +1,39 @@
+import os, sys
+import locale
+import gettext
+
+APP_NAME = "mussorgsky"
+
+APP_DIR = os.path.join (sys.prefix,
+                        'share',
+                        APP_NAME)
+
+LOCALE_DIR = os.path.join(APP_DIR, 'locale')
+
+DEFAULT_LANGUAGES = os.environ.get('LANGUAGE', '').split(':')
+DEFAULT_LANGUAGES += ['en_US']
+
+# Init i18n stuff
+lc, encoding = locale.getdefaultlocale()
+
+if lc:
+    languages = [lc]
+
+# DEBUG: to test translation without installation
+#languages = ["es_ES"]
+#mo_location = os.path.realpath(os.path.dirname(sys.argv[1]))
+#print languages
+
+languages += DEFAULT_LANGUAGES
+mo_location = LOCALE_DIR
+
+#print "Loading translations from: ", mo_location
+
+gettext.install (True)
+gettext.bindtextdomain (APP_NAME,
+                        mo_location)
+gettext.textdomain (APP_NAME)
+language = gettext.translation (APP_NAME,
+                                mo_location,
+                                languages = languages,
+                                fallback = True)
index 60ee035..2a5df4c 100755 (executable)
@@ -6,10 +6,16 @@ from album_art_panel import MussorgskyAlbumArtPanel
 from browse_panel import MussorgskyBrowsePanel
 from fancy_button import FancyButton, settings_changed
 
+import i18n
+_ = i18n.language.gettext
+
 class MussorgskyMainWindow (hildon.StackableWindow):
 
     def __init__ (self):
         hildon.StackableWindow.__init__ (self)
+
+
+        
         self.tracker = TrackerBackend ()
         self.set_title ("MussOrgsky")
         self.set_border_width (12)
@@ -48,13 +54,13 @@ class MussorgskyMainWindow (hildon.StackableWindow):
         hbox = gtk.HBox ()
 
         align1 = gtk.Alignment (xalign=0.5, yalign=0.5)
-        button1 = FancyButton (image1, "Browse metadata")
+        button1 = FancyButton (image1, _("Metadata"))
         button1.connect ("clicked", self.browse_clicked)
         align1.add (button1)
         hbox.pack_start (align1)
 
         align2 = gtk.Alignment (xalign=0.5, yalign=0.5)
-        button2 = FancyButton(image2, "Album art")
+        button2 = FancyButton(image2, _("Album art"))
         button2.connect ("clicked", self.album_art_clicked)
         align2.add (button2)
         hbox.pack_start (align2)
@@ -64,6 +70,7 @@ class MussorgskyMainWindow (hildon.StackableWindow):
 
 if __name__ == "__main__":
 
+
     try:
         window = MussorgskyMainWindow ()