Ensure that the rendered dates are always in the same language as the calibre interface, regardless of system language setting

This commit is contained in:
Kovid Goyal 2014-04-06 13:28:32 +05:30
parent 99a63ab65a
commit b12b60da40
5 changed files with 3953 additions and 21 deletions

3901
setup/lc_data.py Normal file

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,8 @@ __license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>' __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import os, tempfile, shutil, subprocess, glob, re, time, textwrap import os, tempfile, shutil, subprocess, glob, re, time, textwrap, cPickle
from locale import normalize as normalize_locale
from functools import partial from functools import partial
from setup import Command, __appname__, __version__, require_git_master from setup import Command, __appname__, __version__, require_git_master
@ -150,6 +151,9 @@ class Translations(POT): # {{{
return locale, os.path.join(self.DEST, locale, 'messages.mo') return locale, os.path.join(self.DEST, locale, 'messages.mo')
def run(self, opts): def run(self, opts):
l = {}
execfile(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'lc_data.py'), l, l)
lcdata = {k:{k1:v1 for k1, v1 in v} for k, v in l['data']}
self.iso639_errors = [] self.iso639_errors = []
for f in self.po_files(): for f in self.po_files():
locale, dest = self.mo_file(f) locale, dest = self.mo_file(f)
@ -173,6 +177,13 @@ class Translations(POT): # {{{
'jv', 'ka', 'fur', 'ber', 'my', 'fil'}: 'jv', 'ka', 'fur', 'ber', 'my', 'fil'}:
self.warn('No ISO 639 translations for locale:', locale) self.warn('No ISO 639 translations for locale:', locale)
ln = normalize_locale(locale).partition('.')[0]
if ln in lcdata:
ld = lcdata[ln]
lcdest = self.j(self.d(dest), 'lcdata.pickle')
with open(lcdest, 'wb') as lcf:
lcf.write(cPickle.dumps(ld, -1))
if self.iso639_errors: if self.iso639_errors:
for err in self.iso639_errors: for err in self.iso639_errors:
print (err) print (err)

View File

@ -9,7 +9,7 @@ from PyQt4.Qt import (QVariant, QFileInfo, QObject, QBuffer, Qt,
QEvent, QTimer, pyqtSignal, QDateTime, QDesktopServices, QEvent, QTimer, pyqtSignal, QDateTime, QDesktopServices,
QFileDialog, QFileIconProvider, QSettings, QColor, QFileDialog, QFileIconProvider, QSettings, QColor,
QIcon, QApplication, QDialog, QUrl, QFont, QPalette, QIcon, QApplication, QDialog, QUrl, QFont, QPalette,
QFontDatabase) QFontDatabase, QLocale)
ORG_NAME = 'KovidsBrain' ORG_NAME = 'KovidsBrain'
APP_UID = 'libprs500' APP_UID = 'libprs500'
@ -19,6 +19,7 @@ from calibre.constants import (islinux, iswindows, isbsd, isfrozen, isosx,
from calibre.utils.config import Config, ConfigProxy, dynamic, JSONConfig from calibre.utils.config import Config, ConfigProxy, dynamic, JSONConfig
from calibre.ebooks.metadata import MetaInformation from calibre.ebooks.metadata import MetaInformation
from calibre.utils.date import UNDEFINED_DATE from calibre.utils.date import UNDEFINED_DATE
from calibre.utils.localization import get_lang
# Setup gprefs {{{ # Setup gprefs {{{
gprefs = JSONConfig('gui') gprefs = JSONConfig('gui')
@ -873,6 +874,9 @@ class Application(QApplication):
if DEBUG: if DEBUG:
self.redirect_notify = True self.redirect_notify = True
QApplication.__init__(self, qargs) QApplication.__init__(self, qargs)
dl = QLocale(get_lang())
if unicode(dl.bcp47Name()) != u'C':
QLocale.setDefault(dl)
global gui_thread, qt_app global gui_thread, qt_app
gui_thread = QThread.currentThread() gui_thread = QThread.currentThread()
self._translator = None self._translator = None

View File

@ -13,6 +13,7 @@ from functools import partial
from dateutil.tz import tzlocal, tzutc, EPOCHORDINAL from dateutil.tz import tzlocal, tzutc, EPOCHORDINAL
from calibre import strftime from calibre import strftime
from calibre.utils.localization import lcdata
class SafeLocalTimeZone(tzlocal): class SafeLocalTimeZone(tzlocal):
@ -231,7 +232,7 @@ def timestampfromdt(dt, assume_utc=True):
# Format date functions # Format date functions
def fd_format_hour(dt, strf, ampm, hr): def fd_format_hour(dt, ampm, hr):
l = len(hr) l = len(hr)
h = dt.hour h = dt.hour
if ampm: if ampm:
@ -240,45 +241,41 @@ def fd_format_hour(dt, strf, ampm, hr):
return '%d'%h return '%d'%h
return '%02d'%h return '%02d'%h
def fd_format_minute(dt, strf, ampm, min): def fd_format_minute(dt, ampm, min):
l = len(min) l = len(min)
if l == 1: if l == 1:
return '%d'%dt.minute return '%d'%dt.minute
return '%02d'%dt.minute return '%02d'%dt.minute
def fd_format_second(dt, strf, ampm, sec): def fd_format_second(dt, ampm, sec):
l = len(sec) l = len(sec)
if l == 1: if l == 1:
return '%d'%dt.second return '%d'%dt.second
return '%02d'%dt.second return '%02d'%dt.second
def fd_format_ampm(dt, strf, ampm, ap): def fd_format_ampm(dt, ampm, ap):
res = strf('%p') res = strftime('%p', t=dt.timetuple())
if ap == 'AP': if ap == 'AP':
return res return res
return res.lower() return res.lower()
def fd_format_day(dt, strf, ampm, dy): def fd_format_day(dt, ampm, dy):
l = len(dy) l = len(dy)
if l == 1: if l == 1:
return '%d'%dt.day return '%d'%dt.day
if l == 2: if l == 2:
return '%02d'%dt.day return '%02d'%dt.day
if l == 3: return lcdata['abday' if l == 3 else 'day'][(dt.weekday() + 1) % 7]
return strf('%a')
return strf('%A')
def fd_format_month(dt, strf, ampm, mo): def fd_format_month(dt, ampm, mo):
l = len(mo) l = len(mo)
if l == 1: if l == 1:
return '%d'%dt.month return '%d'%dt.month
if l == 2: if l == 2:
return '%02d'%dt.month return '%02d'%dt.month
if l == 3: return lcdata['abmon' if l == 3 else 'mon'][dt.month - 1]
return strf('%b')
return strf('%B')
def fd_format_year(dt, strf, ampm, yr): def fd_format_year(dt, ampm, yr):
if len(yr) == 2: if len(yr) == 2:
return '%02d'%(dt.year % 100) return '%02d'%(dt.year % 100)
return '%04d'%dt.year return '%04d'%dt.year
@ -293,11 +290,11 @@ fd_function_index = {
'a': fd_format_ampm, 'a': fd_format_ampm,
'A': fd_format_ampm, 'A': fd_format_ampm,
} }
def fd_repl_func(dt, strf, ampm, mo): def fd_repl_func(dt, ampm, mo):
s = mo.group(0) s = mo.group(0)
if not s: if not s:
return '' return ''
return fd_function_index[s[0]](dt, strf, ampm, s) return fd_function_index[s[0]](dt, ampm, s)
def format_date(dt, format, assume_utc=False, as_utc=False): def format_date(dt, format, assume_utc=False, as_utc=False):
''' Return a date formatted as a string using a subset of Qt's formatting codes ''' ''' Return a date formatted as a string using a subset of Qt's formatting codes '''
@ -319,8 +316,7 @@ def format_date(dt, format, assume_utc=False, as_utc=False):
if dt == UNDEFINED_DATE: if dt == UNDEFINED_DATE:
return '' return ''
strf = partial(strftime, t=dt.timetuple()) repl_func = partial(fd_repl_func, dt, 'ap' in format.lower())
repl_func = partial(fd_repl_func, dt, strf, 'ap' in format.lower())
return re.sub( return re.sub(
'(s{1,2})|(m{1,2})|(h{1,2})|(ap)|(AP)|(d{1,4}|M{1,4}|(?:yyyy|yy))', '(s{1,2})|(m{1,2})|(h{1,2})|(ap)|(AP)|(d{1,4}|M{1,4}|(?:yyyy|yy))',
repl_func, format) repl_func, format)

View File

@ -100,8 +100,23 @@ def get_all_translators():
buf = cStringIO.StringIO(zf.read(mpath + '/messages.mo')) buf = cStringIO.StringIO(zf.read(mpath + '/messages.mo'))
yield lang, GNUTranslations(buf) yield lang, GNUTranslations(buf)
lcdata = {
u'abday': (u'Sun', u'Mon', u'Tue', u'Wed', u'Thu', u'Fri', u'Sat'),
u'abmon': (u'Jan', u'Feb', u'Mar', u'Apr', u'May', u'Jun', u'Jul', u'Aug', u'Sep', u'Oct', u'Nov', u'Dec'),
u'd_fmt': u'%m/%d/%Y',
u'd_t_fmt': u'%a %d %b %Y %r %Z',
u'day': (u'Sunday', u'Monday', u'Tuesday', u'Wednesday', u'Thursday', u'Friday', u'Saturday'),
u'mon': (u'January', u'February', u'March', u'April', u'May', u'June', u'July', u'August', u'September', u'October', u'November', u'December'),
u'noexpr': u'^[nN].*',
u'radixchar': u'.',
u't_fmt': u'%r',
u't_fmt_ampm': u'%I:%M:%S %p',
u'thousep': u',',
u'yesexpr': u'^[yY].*'
}
def set_translators(): def set_translators():
global _lang_trans global _lang_trans, lcdata
# To test different translations invoke as # To test different translations invoke as
# CALIBRE_OVERRIDE_LANG=de_DE.utf8 program # CALIBRE_OVERRIDE_LANG=de_DE.utf8 program
lang = get_lang() lang = get_lang()
@ -135,6 +150,11 @@ def set_translators():
iso639 = cStringIO.StringIO(zf.read(isof)) iso639 = cStringIO.StringIO(zf.read(isof))
except: except:
pass # No iso639 translations for this lang pass # No iso639 translations for this lang
if buf is not None:
try:
lcdata = cPickle.loads(zf.read(mpath + '/lcdata.pickle'))
except:
pass # No lcdata
if buf is not None: if buf is not None:
t = GNUTranslations(buf) t = GNUTranslations(buf)