Python Forum

Full Version: decimal point or comma
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
rather than deal with the complexity of internationalization where i need to have my own code fill in the decimal point or use decimal scaling separators (i never knew what to call it where "12345678" is made to look like "12,345,678") i am thinking of doing:
    decpnt = str(1.5)[1]
    decsep = ',' if decpnt=='.' else '.'
does this seem reasonable?
Only if I understand what you were asking. Is the question, where the decimal point should be placed? Or is the question have i placed my point at the right index?
neither. it is whether the code is reasonable to determine which characters are being used in which place. is it ',' and '.' or '.' and ',' (or maybe even something else)?
(Mar-12-2019, 07:45 PM)Skaperen Wrote: [ -> ]where "12345678" is made to look like "12,345,678")
>>> f'{12345678:_}'
'12_345_678'
Skaperen Wrote:or maybe even something else
PEP 515 Wink
>>> 10_500 + 25_123
35623
>>> 10_000_000 + 5
10000005
>>> f'{1000000000:_}'
'1_000_000_000'
If you do real i18n, not toy applications, you should avoid building your own stuff.
For i18n support: locale, gettext and hopefully other tools are used.
gettext is very verbose. There are better tools.

For l10n there are graphical tools for translators. They load the po file, save the translations as pot (if I remind right) and then they give it back to the programmer. The programmer runs msgfmt to create the binary blobs for the domain.

To implement it by your own, you have to know much about languages. Russian people have different forms of plural.
Then every country has a different symbol for currency. Different date formats and timezones (pytz).
and different countries group digits in different ways, too. many countries group decimal digits in 4s, while India and Pakistan group by 2s after an initial group of 3.

if you look more closely at my code you can see that it bases things on what is already. i could do more of that as needed. line 1 gets the character used for decimal points so i can pass it to the .split() method. i did not see an i18n way to do that split.
you can use this function

Total = 12345678
print("Total cost is: {:,.2f}".format(Total)) 
the result will be look like below
12,345,678.00
will it do the right thing when the internationalization shows that it is in other places where the right way looks like "12.345.678,00" or "1234.5678,00" or "1,23,45,678.00"?
Here are my tries to work with locale and gettext.
In other words: It's pain in the a....


from pathlib import Path
import locale
from locale import (
    LC_ALL,
    LC_NUMERIC,
    setlocale,
    getlocale,
    getdefaultlocale,
    currency
    )
from locale import format_string as lformat
import gettext

def translations(domain, localedir):
    localedir = Path(localedir)
    result = {}
    for trans in localedir.glob(f'**/{domain}.mo'):
        lang = trans.parent.parent.name
        print(f'Found translation {trans}. Language: {lang}')
        try:
            result[lang] = gettext.translation(domain, localedir, [lang])
        except Exception as e:
            print(e)
    print()
    return result

trans = translations('messages', 'translations')


def current_setting():
    for symbol in dir(locale):
        if symbol.startswith('LC_') and symbol != 'LC_ALL':
            tp = getattr(locale, symbol)
            print(f'{symbol:<20}{locale.getlocale(tp)}')
    print()

def test():
    current_setting()
    try:
        print(currency(val))
    except ValueError as e:
        print(e)
    print(lformat('%.2f', val, grouping=True))
    print(_('Hello World!'))
    print()

val = 1337.42
defaultlocale = getdefaultlocale()
print('Defaultlocale is', defaultlocale)
print()

setlocale(LC_ALL, 'en_US.utf8')
trans['en_US'].install()
test()

setlocale(LC_ALL, 'en_US.utf8')
print('LC_ALL set to en_US.utf8')
trans['en_GB'].install()
test()

trans['de_DE'].install()
ret = setlocale(LC_ALL, defaultlocale)
print('LC_ALL set to', ret)
test()
Output
Output:
Found translation translations/en_US/LC_MESSAGES/messages.mo. Language: en_US Found translation translations/en_GB/LC_MESSAGES/messages.mo. Language: en_GB Found translation translations/de_DE/LC_MESSAGES/messages.mo. Language: de_DE Defaultlocale is ('de_DE', 'UTF-8') LC_COLLATE ('en_US', 'UTF-8') LC_CTYPE ('en_US', 'UTF-8') LC_MESSAGES ('en_US', 'UTF-8') LC_MONETARY ('en_US', 'UTF-8') LC_NUMERIC ('en_US', 'UTF-8') LC_TIME ('en_US', 'UTF-8') $1337.42 1,337.42 Fuck You! LC_ALL set to en_US.utf8 LC_COLLATE ('en_US', 'UTF-8') LC_CTYPE ('en_US', 'UTF-8') LC_MESSAGES ('en_US', 'UTF-8') LC_MONETARY ('en_US', 'UTF-8') LC_NUMERIC ('en_US', 'UTF-8') LC_TIME ('en_US', 'UTF-8') $1337.42 1,337.42 Hello World! LC_ALL set to de_DE.UTF-8 LC_COLLATE ('de_DE', 'UTF-8') LC_CTYPE ('de_DE', 'UTF-8') LC_MESSAGES ('de_DE', 'UTF-8') LC_MONETARY ('de_DE', 'UTF-8') LC_NUMERIC ('de_DE', 'UTF-8') LC_TIME ('de_DE', 'UTF-8') 1337,42 € 1.337,42 Hallo Welt!
I could not test with locale en_GB, because I haven't installed it on my system.