feat: Support for short compact currency formats by DenverCoder1 · Pull Request #926 · python-babel/babel

Conversation

@DenverCoder1

Added a way to format currency with standard "short" currency formats from the CLDR data.

Closes #923

>>> format_compact_currency(123456789, 'USD', locale='en_US', fraction_digits=2)
u'$123.46M'

>>> format_compact_currency(-123456789, 'USD', locale='en_US', fraction_digits=2)
u'-$123.46M'

>>> Format("en_US").compact_currency(123456789, 'USD', fraction_digits=2)
u'$123.46M'

"short" is currently the only length type that seems to appear in the data.

Note: "standard:short" no longer appears in locale.currency_formats (see #923). This was never documented or tested and did not format things properly in the first place, so I don't think this should be considered a breaking change.

@codecov

Codecov Report

Merging #926 (cdb54de) into master (3add2c1) will increase coverage by 0.04%.
The diff coverage is 100.00%.

@@            Coverage Diff             @@
##           master     #926      +/-   ##
==========================================
+ Coverage   91.55%   91.59%   +0.04%     
==========================================
  Files          21       21              
  Lines        4215     4238      +23     
==========================================
+ Hits         3859     3882      +23     
  Misses        356      356              
Impacted Files Coverage Δ
babel/core.py 96.40% <100.00%> (+0.03%) ⬆️
babel/numbers.py 97.93% <100.00%> (+0.10%) ⬆️
babel/support.py 85.08% <100.00%> (+0.12%) ⬆️

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

akx

akx requested changes Nov 2, 2022

akx

akx requested changes Nov 2, 2022

@DenverCoder1

As far as I can tell, CLDR doesn't provide a format for formatting currency in short form for numbers less than 1000.

As a fallback, maybe it would make sense to take the smallest magnitude and remove characters not related to the ordering of the currency symbol and spacing.

Here is what I currently think could be a good fallback:

# find first format that has a currency symbol
for magnitude in compact_format['other']:
    format = compact_format['other'][magnitude].pattern
    if '¤' not in format:
        continue
    # remove characters that are not the currency symbol, 0's or spaces
    format = re.sub(r'[^0\s\¤]', '', format)
    # compress adjacent spaces into one
    format = re.sub(r'(\s)\s+', r'\1', format).strip()
    break

Example:

en_US: 1234 = '€1K' || 123 = '€123'
es: 1234 = '1 mil €' || 123 = '123 €'

I've made a gist to show the results this produces for all locales:

https://gist.github.com/DenverCoder1/e4a1ab9ac94e576a34ad7371f3573e0b

jun66j5

Co-authored-by: Jun Omae (大前 潤) <42682+jun66j5@users.noreply.github.com>

akx

akx approved these changes Nov 4, 2022

@akx akx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Labels