Skip to content

Commit

Permalink
Merge pull request #53 from Luflosi/implement-decimal-sep-i18n
Browse files Browse the repository at this point in the history
  • Loading branch information
hugovk authored Aug 30, 2022
2 parents d8e2739 + 862748a commit 72d3ef4
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 6 deletions.
3 changes: 2 additions & 1 deletion src/humanize/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Main package for humanize."""

from humanize.filesize import naturalsize
from humanize.i18n import activate, deactivate, thousands_separator
from humanize.i18n import activate, deactivate, decimal_separator, thousands_separator
from humanize.number import (
apnumber,
clamp,
Expand Down Expand Up @@ -36,6 +36,7 @@
"apnumber",
"clamp",
"deactivate",
"decimal_separator",
"fractional",
"intcomma",
"intword",
Expand Down
20 changes: 19 additions & 1 deletion src/humanize/i18n.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import os.path
from threading import local

__all__ = ["activate", "deactivate", "thousands_separator"]
__all__ = ["activate", "deactivate", "decimal_separator", "thousands_separator"]

_TRANSLATIONS: dict[str | None, gettext_module.NullTranslations] = {
None: gettext_module.NullTranslations()
Expand All @@ -19,6 +19,11 @@
"fr_FR": " ",
}

# Mapping of locale to decimal separator
_DECIMAL_SEPARATOR = {
"de_DE": ",",
}


def _get_default_locale_path() -> str | None:
try:
Expand Down Expand Up @@ -173,3 +178,16 @@ def thousands_separator() -> str:
except (AttributeError, KeyError):
sep = ","
return sep


def decimal_separator() -> str:
"""Return the decimal separator for a locale, default to dot.
Returns:
str: Decimal separator.
"""
try:
sep = _DECIMAL_SEPARATOR[_CURRENT.locale]
except (AttributeError, KeyError):
sep = "."
return sep
10 changes: 6 additions & 4 deletions src/humanize/number.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from .i18n import _ngettext
from .i18n import _ngettext_noop as NS_
from .i18n import _pgettext as P_
from .i18n import thousands_separator
from .i18n import decimal_separator, thousands_separator

if TYPE_CHECKING:
if sys.version_info >= (3, 10):
Expand Down Expand Up @@ -130,10 +130,11 @@ def intcomma(value: NumberOrString, ndigits: int | None = None) -> str:
Returns:
str: String containing commas every three digits.
"""
sep = thousands_separator()
thousands_sep = thousands_separator()
decimal_sep = decimal_separator()
try:
if isinstance(value, str):
value = value.replace(sep, "")
value = value.replace(thousands_sep, "").replace(decimal_sep, ".")
if "." in value:
value = float(value)
else:
Expand All @@ -147,8 +148,9 @@ def intcomma(value: NumberOrString, ndigits: int | None = None) -> str:
orig = "{0:.{1}f}".format(value, ndigits)
else:
orig = str(value)
orig = orig.replace(".", decimal_sep)
while True:
new = re.sub(r"^(-?\d+)(\d{3})", rf"\g<1>{sep}\g<2>", orig)
new = re.sub(r"^(-?\d+)(\d{3})", rf"\g<1>{thousands_sep}\g<2>", orig)
if orig == new:
return new
orig = new
Expand Down
6 changes: 6 additions & 0 deletions tests/test_i18n.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ def test_intcomma() -> None:
try:
humanize.i18n.activate("de_DE")
assert humanize.intcomma(number) == "10.000.000"
assert humanize.intcomma(1_234_567.8901) == "1.234.567,8901"
assert humanize.intcomma(1_234_567.89) == "1.234.567,89"
assert humanize.intcomma("1234567,89") == "1.234.567,89"
assert humanize.intcomma("1.234.567,89") == "1.234.567,89"
assert humanize.intcomma("1.234.567,8") == "1.234.567,8"

humanize.i18n.activate("fr_FR")
assert humanize.intcomma(number) == "10 000 000"

Expand Down

0 comments on commit 72d3ef4

Please sign in to comment.