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>'
__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 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')
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 = []
for f in self.po_files():
locale, dest = self.mo_file(f)
@ -173,6 +177,13 @@ class Translations(POT): # {{{
'jv', 'ka', 'fur', 'ber', 'my', 'fil'}:
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:
for err in self.iso639_errors:
print (err)

View File

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

View File

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

View File

@ -100,8 +100,23 @@ def get_all_translators():
buf = cStringIO.StringIO(zf.read(mpath + '/messages.mo'))
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():
global _lang_trans
global _lang_trans, lcdata
# To test different translations invoke as
# CALIBRE_OVERRIDE_LANG=de_DE.utf8 program
lang = get_lang()
@ -135,6 +150,11 @@ def set_translators():
iso639 = cStringIO.StringIO(zf.read(isof))
except:
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:
t = GNUTranslations(buf)