forked from ospalh/anki-addons
-
Notifications
You must be signed in to change notification settings - Fork 1
/
swiss_locale.py
191 lines (162 loc) · 6.42 KB
/
swiss_locale.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# -*- mode: python ; coding: utf-8 -*-
# © Roland Sieker <ospalh@gmail.com>
# Based on code by Damien Elmes <anki@ichi2.net>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
# Based off Kieran Clancy's initial implementation.
"""
Anki-2 add-on to format numbers just the way i like them.
"""
# Usually Python comes with 'batteries included', that is, with the
# Python standard library. Unfortunately, this is not the case for a
# typical Anki install. So bring along some files that are
# missing. Make sure we find them.
from aqt import mw # We need this to get to the path
# These *are* available with standard Anki
import os
import sys
import locale
from anki.hooks import addHook
from anki.utils import isMac
# Add the path, but only once. (Other add-ons by YT contain similar
# code.)
if not [pe for pe in sys.path if 'batteries' in pe]:
sys.path.append(os.path.join(mw.pm.addonFolder(), "batteries"))
# Now this should work. Include module to deal with numbers digit by
# digit.
import decimal
# I personally like the Swiss use of the apostroph as thousands separator.
# locale.setlocale(locale.LC_NUMERIC, 'de_CH.UTF-8')
__version__ = '1.1.4'
millions_word = (u' <span class="number_romaji">Millionen</span>')
billions_word = (u' <span class="number_romaji">Milliarden</span>')
arab_format_string = '<span class="number_arab">{0}</span>'
def swiss_format(num):
"""
Return the number num as a string with Swiss formating.
Return the number num as a string with Swiss formating, but don't
use a thousands separator for numbers < 10'000. Also wrap the
number in a span with class number_arab.
There seems to be a problem with locales on Macs, so just wrap in
the span there.
"""
do_group = (num >= 10000)
if not isMac:
# AFAIK loading locales on Macs didn't throw an exception, but
# gave ugly layout. So don't try it there.
try:
# On the other hand, i have problems loading the swiss
# locale on some other systems. So only try it.
locale.setlocale(locale.LC_NUMERIC, ('de_CH', 'UTF-8'))
except locale.Error:
num_string = str(num)
else:
num_string = locale.format('%d', num, grouping=do_group)
else:
num_string = str(num)
return arab_format_string.format(num_string)
def ch_millionen(txt, *dummy_args):
"""
Return the text reformated for my geography deck.
* Return txt when it is not a number or when it is 0
* Return txt multiplied by 1'000'000 when it is <1
* Return txt with the words Millionen added when it is >=1 and <
1000
* Return txt with the words Billionen added when it is >= 1000
When txt is reformated, it uses the Swiss thousands separator of "'".
This gives nice formating for inhabitans numbers in my geography deck.
"""
# Total rework. RAS 2012-09-06
# Parts taken from my "days" script, see
# https://github.com/ospalh/age/blob/master/days
try:
dec_mega = decimal.Decimal(txt)
except decimal.InvalidOperation:
# No number
return txt
if 0 == dec_mega:
# Case "0 Einwohner" == "0 Millionen Einwohner"
return txt
dummy_dms, dmd, dme = dec_mega.as_tuple()
# order of magnitude +1
omagp = len(dmd) + dme
# billons
if omagp >= 4:
return arab_format_string.format(float(dec_mega) / 1000.0)\
+ billions_word
# Full millions
if dme >= 0:
# No need to do the swiss formating here. It is the point of
# the billions exercise that we have <1000 million here. And we don't
# really need it until 10 billions.
return arab_format_string.format(int(dec_mega)) + millions_word
# Less than a million or something like 3.5 million.
return swiss_format(int(dec_mega * 1000000))
def ch_t_sqkm(txt, *dummy_args):
"""
Return the text reformated for my geography deck.
* Return txt when it is not a number
* Return txt multiplied by 1'000 with km<sup>2</sup> added when it is <1000
* Return txt divided by 1'000 with Mm<sup>2</sup> added when it is >=1000
When txt is reformated, it uses the Swiss thousands separator of "'".
The text is also wrapped in some classes.
This gives nice formating for area numbers in my geography deck.
"""
# Total rework. RAS 2012-09-06
# Parts taken from my "days" script, see
# https://github.com/ospalh/age/blob/master/days
try:
dec_kilo = decimal.Decimal(txt)
except decimal.InvalidOperation:
# No number
return txt
dummy_dks, dkd, dke = dec_kilo.as_tuple()
# order of magnitude +1
omagp = len(dkd) + dke
if omagp >= 4:
return arab_format_string.format(float(dec_kilo) / 1000.0) + \
u' <span class="number_romaji">Mm<sup>2</sup></span>'
if dke < -3:
return arab_format_string.format(float(dec_kilo) * 1000.0) + \
u' <span class="number_romaji">km<sup>2</sup></span>'
return swiss_format(int(dec_kilo * 1000)) + \
u' <span class="number_romaji">km<sup>2</sup></span>'
def jp_man(txt, *dummy_args):
"""
Return the text reformated for my geography deck.
* Return txt when it is not a number
* Return txt multiplied by 1'000 when it is <10
* Return txt divided by 10 with "万" added when it is >=10
The text is also wrapped in some classes.
This gives nice formating for area numbers for Japanese
prefectures in my geography deck.
"""
# Total rework. RAS 2012-09-06
# Parts taken from my "days" script, see
# https://github.com/ospalh/age/blob/master/days
try:
dec_kilo = decimal.Decimal(txt)
except decimal.InvalidOperation:
# No number
return txt
dummy_dks, dkd, dke = dec_kilo.as_tuple()
# order of magnitude +1
omagp = len(dkd) + dke
# We cheat a bit. We know that we won’t have 一億km². No check for
# >=6.
if omagp >= 2:
return arab_format_string.format(float(dec_kilo) / 10.0) + \
u'<span class="number_kanji">万</span>'
return arab_format_string.format(int(dec_kilo * 1000))
def ch_integer(txt, *dummy_args):
"""
Return text formated as a swiss integer if possible.
"""
try:
s_int = int(txt)
except ValueError:
return txt
return swiss_format(s_int)
addHook('fmod_swissmega', ch_millionen)
addHook('fmod_swisssqkm', ch_t_sqkm)
addHook('fmod_swissint', ch_integer)
addHook('fmod_jpman', jp_man)