Fix gettext plural forms (Maemo bug 6885)

Implement proper plural forms for languages
with more than two plural forms by using
ungettext and properly using it for plurals.

Thanks to Tomasz Dominikowski for reporting.
This commit is contained in:
Thomas Perl 2009-12-21 23:18:00 +01:00
parent fbb7343d7d
commit 63dc89e6f4
10 changed files with 57 additions and 78 deletions

View File

@ -134,7 +134,7 @@ data/ui/%.ui.h: $(subst .ui.h,.h,$@)
intltool-extract --type=gettext/glade $(subst .ui.h,.ui,$@)
$(MESSAGESPOT): src/gpodder/*.py $(BINFILE) $(UIFILES_H) $(TRANSLATABLE_SOURCE)
xgettext -k_ -kN_ -o $(MESSAGESPOT) $(TRANSLATABLE_SOURCE) $(UIFILES_H) $(BINFILE)
xgettext -k_:1 -kN_:1,2 -o $(MESSAGESPOT) $(TRANSLATABLE_SOURCE) $(UIFILES_H) $(BINFILE)
sed -i'~' -e 's/SOME DESCRIPTIVE TITLE/gPodder translation template/g' -e 's/YEAR THE PACKAGE'"'"'S COPYRIGHT HOLDER/2006 Thomas Perl/g' -e 's/FIRST AUTHOR <EMAIL@ADDRESS>, YEAR/Thomas Perl <thp@perli.net>, 2006/g' -e 's/PACKAGE VERSION/gPodder '$(GPODDERVERSION)'/g' -e 's/PACKAGE/gPodder/g' $(MESSAGESPOT)
rosetta-upload: $(ROSETTA_ARCHIVE)

View File

@ -72,6 +72,7 @@ textdomain = 'gpodder'
locale_dir = gettext.bindtextdomain(textdomain)
t = gettext.translation(textdomain, locale_dir, fallback=True)
gettext = t.ugettext
ngettext = t.ungettext
del t
# Set up textdomain for gtk.Builder (this accesses the C library functions)

View File

@ -24,6 +24,7 @@ from xml.sax import saxutils
import gpodder
_ = gpodder.gettext
N_ = gpodder.ngettext
from gpodder import util
from gpodder.liblogger import log
@ -318,10 +319,7 @@ class gPodderEpisodeSelector(BuilderWidget):
text = []
if count == 0:
text.append(_('Nothing selected'))
elif count == 1:
text.append(_('One episode'))
else:
text.append(_('%d episodes') % count)
text.append(N_('%d episode', '%d episodes', count) % count)
if total_size > 0:
text.append(_('size: %s') % util.format_filesize(total_size))
self.labelTotalSize.set_text(', '.join(text))

View File

@ -29,6 +29,7 @@ import gpodder
from gpodder.liblogger import log
_ = gpodder.gettext
N_ = gpodder.ngettext
from gpodder import services
from gpodder import util
@ -225,10 +226,7 @@ class GPodderStatusIcon(gtk.StatusIcon):
more_episodes = len(episode_list) - max_episodes
if more_episodes > 0:
result.append('(...')
if more_episodes == 1:
result.append(_('one more episode'))
else:
result.append(_('%d more episodes') % more_episodes)
result.append(N_('%d more episode', '%d more episodes', more_episodes) % more_episodes)
result.append('...)')
return (''.join(result)).strip()

View File

@ -24,6 +24,7 @@ from xml.sax import saxutils
import gpodder
_ = gpodder.gettext
N_ = gpodder.ngettext
from gpodder import util
from gpodder.liblogger import log
@ -281,10 +282,8 @@ class gPodderEpisodeSelector(BuilderWidget):
text = []
if count == 0:
text.append(_('Nothing selected'))
elif count == 1:
text.append(_('One episode'))
else:
text.append(_('%d episodes') % count)
text.append(N_('%d episode', '%d episodes', count) % count)
if total_size > 0:
text.append(_('size: %s') % util.format_filesize(total_size))
self.labelTotalSize.set_text(', '.join(text))

View File

@ -28,6 +28,7 @@ import gobject
import gpodder
_ = gpodder.gettext
N_ = gpodder.ngettext
from gpodder import util
from gpodder import opml
@ -255,16 +256,14 @@ class gPodderPodcastDirectory(BuilderWidget):
def set_subscribe_button_sensitive(self):
selection = self.treeview.get_selection()
title = self.main_window.get_title()
title = [self.main_window.get_title()]
if selection:
count = selection.count_selected_rows()
if count == 1:
title += ' - %s' % (_('1 podcast selected'),)
elif count > 1:
title += ' - %s' % (_('%d podcasts selected') % count,)
text = N_('%d podcast selected', '%d podcasts selected', count)
title.append(text % count)
else:
count = 0
self.edit_toolbar.set_label(title)
self.edit_toolbar.set_label(' - '.join(title))
self.edit_toolbar.set_button_sensitive(count > 0)
def on_subscribe_button_clicked(self, widget, *args):

View File

@ -22,6 +22,7 @@ import gtk
import gpodder
_ = gpodder.gettext
N_ = gpodder.ngettext
from gpodder import util
@ -33,9 +34,9 @@ import hildon
class gPodderPreferences(BuilderWidget):
UPDATE_INTERVALS = (
(0, _('manually')),
(20, _('every %d minutes') % 20),
(20, N_('every %d minute', 'every %d minutes', 20) % 20),
(60, _('hourly')),
(60*6, _('every %d hours') % 6),
(60*6, N_('every %d hour', 'every %d hours', 6) % 6),
(60*24, _('daily')),
)

View File

@ -24,6 +24,7 @@ from xml.sax import saxutils
import gpodder
_ = gpodder.gettext
N_ = gpodder.ngettext
from gpodder import util
from gpodder.liblogger import log
@ -296,13 +297,12 @@ class gPodderEpisodeSelector(BuilderWidget):
log( 'Cannot get size for %s', episode.title, sender = self)
text = []
if count == 0:
if count == 0:
text.append(_('Nothing selected'))
elif count == 1:
text.append(_('One episode'))
else:
text.append(_('%d episodes') % count)
if total_size > 0:
text.append(N_('%d episode', '%d episodes', count) % count)
if total_size > 0:
text.append(_('size: %s') % util.format_filesize(total_size))
self.labelTotalSize.set_text(', '.join(text))
self.btnOK.set_sensitive(count>0)

View File

@ -71,6 +71,7 @@ from gpodder import my
from gpodder.liblogger import log
_ = gpodder.gettext
N_ = gpodder.ngettext
from gpodder.model import PodcastChannel
from gpodder.dbsqlite import Database
@ -932,13 +933,13 @@ class gPodder(BuilderWidget, dbus.service.Object):
if downloading + failed + finished + queued > 0:
s = []
if downloading > 0:
s.append(_('%d active') % downloading)
s.append(N_('%d active', '%d active', downloading) % downloading)
if failed > 0:
s.append(_('%d failed') % failed)
s.append(N_('%d failed', '%d failed', failed) % failed)
if finished > 0:
s.append(_('%d done') % finished)
s.append(N_('%d done', '%d done', finished) % finished)
if queued > 0:
s.append(_('%d queued') % queued)
s.append(N_('%d queued', '%d queued', queued) % queued)
text.append(' (' + ', '.join(s)+')')
self.labelDownloads.set_text(''.join(text))
elif gpodder.ui.diablo:
@ -949,11 +950,11 @@ class gPodder(BuilderWidget, dbus.service.Object):
self.tool_downloads.set_label(_('Downloads'))
elif gpodder.ui.fremantle:
if downloading + queued > 0:
self.button_downloads.set_value(_('%d active') % (downloading+queued))
self.button_downloads.set_value(N_('%d active', '%d active', downloading+queued) % (downloading+queued))
elif failed > 0:
self.button_downloads.set_value(_('%d failed') % failed)
self.button_downloads.set_value(N_('%d failed', '%d failed', failed) % failed)
elif paused > 0:
self.button_downloads.set_value(_('%d paused') % paused)
self.button_downloads.set_value(N_('%d paused', '%d paused', paused) % paused)
else:
self.button_downloads.set_value(_('Idle'))
@ -970,10 +971,7 @@ class gPodder(BuilderWidget, dbus.service.Object):
count = downloading + queued
if count > 0:
if count == 1:
title.append( _('downloading one file'))
elif count > 1:
title.append( _('downloading %d files') % count)
title.append(N_('downloading %d file', 'downloading %d files', count) % count)
if total_size > 0:
percentage = 100.0*done_size/total_size
@ -1730,7 +1728,8 @@ class gPodder(BuilderWidget, dbus.service.Object):
if len(episodes) == 1:
text = _('Opening %s') % episodes[0].title
else:
text = _('Opening %d episodes') % len(episodes)
count = len(episodes)
text = N_('Opening %d episode', 'Opening %d episodes', count) % count
banner = hildon.hildon_banner_show_animation(self.gPodder, '', text)
@ -2127,10 +2126,8 @@ class gPodder(BuilderWidget, dbus.service.Object):
if episodes:
if self.config.auto_download == 'always':
if len(episodes) == 1:
title = _('Downloading one new episode.')
else:
title = _('Downloading %d new episodes.') % len(episodes)
count = len(episodes)
title = N_('Downloading %d new episode.', 'Downloading %d new episodes.', count) % count
self.show_message(title)
self.download_episode_list(episodes)
elif self.config.auto_download == 'queue':
@ -2162,16 +2159,13 @@ class gPodder(BuilderWidget, dbus.service.Object):
# btnCancelFeedUpdate is a normal gtk.Button
self.btnCancelFeedUpdate.set_image(gtk.image_new_from_stock(gtk.STOCK_APPLY, gtk.ICON_SIZE_BUTTON))
else:
count = len(episodes)
# New episodes are available
self.pbFeedUpdate.set_fraction(1.0)
# Are we minimized and should we auto download?
if (self.is_iconified() and (self.config.auto_download == 'minimized')) or (self.config.auto_download == 'always'):
self.download_episode_list(episodes)
if len(episodes) == 1:
title = _('Downloading one new episode.')
else:
title = _('Downloading %d new episodes.') % len(episodes)
title = N_('Downloading %d new episode.', 'Downloading %d new episodes.', count) % count
self.show_message(title, _('New episodes available'), widget=self.labelDownloads)
self.show_update_feeds_buttons()
else:
@ -2180,11 +2174,7 @@ class gPodder(BuilderWidget, dbus.service.Object):
if not self.config.do_not_show_new_episodes_dialog:
self.new_episodes_show(episodes, notification=True)
else:
if len(episodes) == 1:
message = _('One new episode is available for download')
else:
message = _('%i new episodes are available for download' % len(episodes))
message = N_('%d new episode available', '%d new episodes available', count) % count
self.pbFeedUpdate.set_text(message)
def _update_cover(self, channel):
@ -2283,11 +2273,12 @@ class gPodder(BuilderWidget, dbus.service.Object):
if self.tray_icon:
self.tray_icon.set_status(self.tray_icon.STATUS_UPDATING_FEED_CACHE)
if len(channels) == 1:
text = _('Updating "%s"...') % channels[0].title
else:
text = _('Updating %d feeds...') % len(channels)
count = len(channels)
text = N_('Updating %d feed...', 'Updating %d feeds...', count) % count
self.pbFeedUpdate.set_text(text)
self.pbFeedUpdate.set_fraction(0)
@ -2410,7 +2401,7 @@ class gPodder(BuilderWidget, dbus.service.Object):
title = _('Remove %s?') % saxutils.escape(episode.title)
message = _("If you remove this episode, it will be deleted from your computer. If you want to listen to this episode again, you will have to re-download it.")
else:
title = _('Remove %d episodes?') % count
title = N_('Remove %d episode?', 'Remove %d episodes?', count) % count
message = _('If you remove these episodes, they will be deleted from your computer. If you want to listen to any of these episodes again, you will have to re-download the episodes in question.')
locked_count = sum(int(e.is_locked) for e in episodes if e.is_locked is not None)
@ -2482,9 +2473,10 @@ class gPodder(BuilderWidget, dbus.service.Object):
('age_prop', None, None, _('Downloaded')),
)
msg_older_than = N_('Select older than %d day', 'Select older than %d days', self.config.episode_old_age)
selection_buttons = {
_('Select played'): lambda episode: episode.is_played,
_('Select older than %d days') % self.config.episode_old_age: lambda episode: episode.age_in_days() > self.config.episode_old_age,
msg_older_than % self.config.episode_old_age: lambda episode: episode.age_in_days() > self.config.episode_old_age,
}
instructions = _('Select the episodes you want to delete:')
@ -2980,10 +2972,8 @@ class gPodder(BuilderWidget, dbus.service.Object):
dlg.destroy()
exporter = opml.Exporter( filename)
if exporter.write(self.channels):
if len(self.channels) == 1:
title = _('One subscription exported')
else:
title = _('%d subscriptions exported') % len(self.channels)
count = len(self.channels)
title = N_('%d subscription exported', '%d subscriptions exported', count) % count
self.show_message(_('Your podcast list has been successfully exported.'), title, widget=self.treeChannels)
else:
self.show_message( _('Could not export OPML to file. Please check your permissions.'), _('OPML export failed'), important=True)

View File

@ -61,6 +61,7 @@ import StringIO
import xml.dom.minidom
_ = gpodder.gettext
N_ = gpodder.ngettext
# Try to detect OS encoding (by Leonid Ponomarev)
@ -334,16 +335,14 @@ def file_age_to_string(days):
>>> file_age_to_string(0)
''
>>> file_age_to_string(1)
u'one day ago'
u'1 day ago'
>>> file_age_to_string(2)
u'2 days ago'
"""
if days == 1:
return _('one day ago')
elif days > 1:
return _('%d days ago') % days
else:
if days < 1:
return ''
else:
return N_('%d day ago', '%d days ago', days) % days
def get_free_disk_space_win32(path):
@ -1008,7 +1007,7 @@ def format_seconds_to_hour_min_sec(seconds):
"""
if seconds < 1:
return _('0 seconds')
return N_('%d second', '%d seconds', seconds) % seconds
result = []
@ -1018,20 +1017,14 @@ def format_seconds_to_hour_min_sec(seconds):
minutes = seconds/60
seconds = seconds%60
if hours == 1:
result.append(_('1 hour'))
elif hours > 1:
result.append(_('%i hours') % hours)
if hours:
result.append(N_('%d hour', '%d hours', hours) % hours)
if minutes == 1:
result.append(_('1 minute'))
elif minutes > 1:
result.append(_('%i minutes') % minutes)
if minutes:
result.append(N_('%d minute', '%d minutes', minutes) % minutes)
if seconds == 1:
result.append(_('1 second'))
elif seconds > 1:
result.append(_('%i seconds') % seconds)
if seconds:
result.append(N_('%d second', '%d seconds', seconds) % seconds)
if len(result) > 1:
return (' '+_('and')+' ').join((', '.join(result[:-1]), result[-1]))