Skip to content

Commit

Permalink
Added basic localizations for humanize
Browse files Browse the repository at this point in the history
Added support for humanize working with different languages (added Russian for example)

New languages support are very basic, and doesn't handle proper changing of nouns plural forms for now.

Updated docs and tests
  • Loading branch information
cleg committed May 8, 2013
1 parent 25abfce commit 2141155
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 16 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ nosetests.xml
local/
dist/
docs/_build/
.idea
.DS_Store
37 changes: 21 additions & 16 deletions arrow/arrow.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
from dateutil.relativedelta import relativedelta
import calendar

import parser, formatter
import parser
import formatter
import locales


class Arrow(object):
Expand Down Expand Up @@ -371,7 +373,7 @@ def ceil(self, frame):
def format(self, fmt):
return formatter.DateTimeFormatter.format(self._datetime, fmt)

def humanize(self, other=None):
def humanize(self, other=None, locale='english'):

if other is None:
utc = datetime.utcnow().replace(tzinfo=dateutil_tz.tzutc())
Expand All @@ -389,45 +391,48 @@ def humanize(self, other=None):
else:
raise TypeError()

local_dict = getattr(locales, locale, None)
if local_dict is None:
raise ValueError('Invalid language {0}'.format(locale))

delta = int((self._datetime - dt).total_seconds())
past = delta < 0
delta = abs(delta)

if delta < 10:
return 'just now'
return local_dict['now']

if delta < 45:
expr = 'seconds'
expr = local_dict['seconds']

elif delta < 90:
expr = 'a minute'
expr = local_dict['minute']
elif delta < 2700:
minutes = max(delta / 60, 2)
expr = '{0} minutes'.format(minutes)
expr = local_dict['minutes'].format(minutes)

elif delta < 5400:
expr = 'an hour'
expr = local_dict['hour']
elif delta < 79200:
hours = max(delta / 3600, 2)
expr = '{0} hours'.format(hours)
expr = local_dict['hours'].format(hours)

elif delta < 129600:
expr = 'a day'
expr = local_dict['day']
elif delta < 2160000:
days = max(delta / 86400, 2)
expr = '{0} days'.format(days)
expr = local_dict['days'].format(days)

elif delta < 3888000:
expr = 'a month'
expr = local_dict['month']
elif delta < 29808000:
months = max(abs(dt.month - self._datetime.month), 2)
expr = '{0} months'.format(months)
expr = local_dict['months'].format(months)

elif delta < 47260800:
expr = 'a year'
expr = local_dict['year']
else:
years = max(delta / 31536000, 2)
expr = '{0} years'.format(years)

return '{0} ago'.format(expr) if past else 'in {0}'.format(expr)
expr = local_dict['years'].format(years)

return local_dict['past'].format(expr) if past else local_dict['future'].format(expr)
37 changes: 37 additions & 0 deletions arrow/locales.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-

english = {
'now': 'just now',
'seconds': 'seconds',
'minute': 'a minute',
'minutes': '{0} minutes',
'hour': 'an hour',
'hours': '{0} hours',
'day': 'a day',
'days': '{0} days',
'month': 'a month',
'months': '{0} months',
'year': 'a year',
'years': '{0} years',

'past': '{0} ago',
'future': 'in {0}',
}

russian = {
'now': 'сейчас',
'seconds': 'несколько секунд',
'minute': 'минуту',
'minutes': '{0} minutes',
'hour': 'час',
'hours': '{0} час(а,ов)',
'day': 'день',
'days': '{0} дня(ей)',
'month': 'месяц',
'months': '{0} месяц(а,ев)',
'year': 'год',
'years': '{0} года/лет',

'past': '{0} назад',
'future': 'через {0}',
}
8 changes: 8 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,14 @@ Or another Arrow, or datetime:
>>> b.humanize(a)
'in 2 hours'

Basic localisations added. Now only russian available (without changing nouns in plural forms), but you can add your language by adding it to `locales.py`

>>> b = arrow.utcnow()
>>> b.hours += 1
>>> b.humanize(a, locale='russian')
'через 2 час(а,ов)'


Timespans
=========

Expand Down
32 changes: 32 additions & 0 deletions tests/arrow_tests.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# -*- coding: utf-8 -*-

from chai import Chai

from datetime import datetime, timedelta
Expand Down Expand Up @@ -665,6 +667,13 @@ def test_other(self):
with assertRaises(TypeError):
arw.humanize(object())

def test_invalid_locale(self):

arw = arrow.Arrow.fromdatetime(self.datetime)

with assertRaises(ValueError):
arw.humanize(locale='klingon')

def test_none(self):

arw = arrow.Arrow.utcnow()
Expand All @@ -673,3 +682,26 @@ def test_none(self):

assertEqual(result, 'just now')


class ArrowHumanizeTestsWithLocale(Chai):

def setUp(self):
super(ArrowHumanizeTestsWithLocale, self).setUp()

self.datetime = datetime(2013, 1, 1)

def test_seconds(self):

arw = arrow.Arrow(2013, 1, 1, 0, 0, 44)

result = arw.humanize(self.datetime, locale='russian')

assertEqual(result, 'через несколько секунд')

def test_years(self):

arw = arrow.Arrow(2011, 7, 2)

result = arw.humanize(self.datetime, locale='russian')

assertEqual(result, '2 года/лет назад')

0 comments on commit 2141155

Please sign in to comment.