Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented language support for humanize. #70

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions language.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package humanize

import (
"encoding/json"
"fmt"
"io/ioutil"
)

// Local type for the ordinals and times.
type Local string

// Ruleset for accessing rules
type Ruleset struct {
Mags magnitudes `json:"magnitudes"`
Inds indicators `json:"indicators"`
Ords [][]string `json:"ordinals"`
}

type magnitudes struct {
Now string
Second string
Minute string
Hour string
Day string
Week string
Month string
Year string

Seconds string
Minutes string
Hours string
Days string
Weeks string
Months string
Years string

Longtime string
}

type indicator struct {
Word string
Fix string
}

type indicators struct {
Before indicator
Later indicator
}

// Local for constant language values
const (
English Local = "en_US"
Turkish Local = "tr_TR"
Uninitialized Local = ""
)

var active = Uninitialized
var ruleset = Ruleset{}

// ValidateLanguage for output
// Must be called before Time or Ordinal function
// If implemented to other functions, call it for not getting
// an error. This function automatically chooses language to English.
func ValidateLanguage() {
if active == Uninitialized {
SetLanguage(English)
}
}

// GetLanguage of the humanizing option.
func GetLanguage() Local {
return active
}

// GetRuleset returns current ruleset option
func GetRuleset() Ruleset {
return ruleset
}

// SetLanguage of the humanizing option.
func SetLanguage(l Local) {
active = l
parseRuleset(l)
UpdateMagnitudes()
}

func parseRuleset(l Local) {
fmt.Println("Reading", "locals/"+string(l)+".json")
f, err := ioutil.ReadFile("locals/" + string(l) + ".json")
if err == nil {
ruleset = Ruleset{}
err := json.Unmarshal(f, &ruleset)
if err != nil {
fmt.Println(err)
}
} else {
fmt.Println("Error ! Can not read file.")
}
}
13 changes: 13 additions & 0 deletions language_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package humanize

import (
"fmt"
"time"
)

func EsxampleTurkish() {
SetLanguage(Turkish)
fmt.Println(Time(time.Now()))
SetLanguage(English)
// Output: şimdi
}
40 changes: 40 additions & 0 deletions locals/en_US.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"magnitudes": {
"now": "now",
"second": "1 second",
"seconds": "%d seconds",
"minute": "1 minute",
"minutes": "%d minutes",
"hour": "1 hour",
"hours": "%d hours",
"day": "1 day",
"days": "%d days",
"week": "1 week",
"weeks": "%d weeks",
"month": "1 month",
"months": "%d months",
"year": "1 year",
"years": "%d years",
"longtime": "a long while"
},

"indicators": {
"before": {
"word": "ago",
"fix": "suffix"
},

"later": {
"word": "from now",
"fix": "suffix"
}
},

"ordinals": [
["%.", "th"],
["%10 1", "st"],
["%10 2", "nd"],
["%10 3", "rd"],
["%100 11 %100 12 %100 13", "th"]
]
}
36 changes: 36 additions & 0 deletions locals/tr_TR.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"magnitudes": {
"now": "şimdi",
"second": "1 saniye",
"seconds": "%d saniye",
"minute": "1 dakika",
"minutes": "%d dakika",
"hour": "1 saat",
"hours": "%d saat",
"day": "1 gün",
"days": "%d gün",
"week": "1 hafta",
"weeks": "%d hafta",
"month": "1 ay",
"months": "%d ay",
"year": "1 yıl",
"years": "%d yıl",
"longtime": "uzun süre"
},

"indicators": {
"before": {
"word": "önce",
"fix": "suffix"
},

"later": {
"word": "sonra",
"fix": "suffix"
}
},

"ordinals": [
["%.", "."]
]
}
57 changes: 53 additions & 4 deletions ordinals.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,60 @@
package humanize

import "strconv"
import (
"strconv"
"strings"
)

// Ordinal gives you the input number in a rank/ordinal format.
//
// Ordinal(3) -> 3rd
func Ordinal(x int) string {
suffix := "th"
func Ordinal(x int) (out string) {
ValidateLanguage()

ordinals := GetRuleset().Ords

for _, rule := range ordinals {
out = applyRule(x, out, rule)
}

out = strconv.Itoa(x) + out

return out
}

func applyRule(x int, in string, rule []string) (out string) {
subRules := strings.SplitAfter(rule[0], "%")
out = in
for _, s := range subRules {
if s == "%" {
continue
}
if s == "." {
out = rule[1]
} else {
if ruleMatches(x, s) {
out = rule[1]
}
}
}

return out
}

func ruleMatches(input int, rule string) bool {
r := strings.Split(rule, " ")
m1, _ := strconv.Atoi(r[0])
m2, _ := strconv.Atoi(r[1])

if input%m1 == m2 {
return true
}

return false
}

/*
suffix := "th"
switch x % 10 {
case 1:
if x%100 != 11 {
Expand All @@ -22,4 +70,5 @@ func Ordinal(x int) string {
}
}
return strconv.Itoa(x) + suffix
}

*/
49 changes: 30 additions & 19 deletions times.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ const (
//
// Time(someT) -> "3 weeks ago"
func Time(then time.Time) string {
return RelTime(then, time.Now(), "ago", "from now")
ValidateLanguage()
return RelTime(
then,
time.Now(),
GetRuleset().Inds.Before.Word,
GetRuleset().Inds.Later.Word,
)
}

// A RelTimeMagnitude struct contains a relative time point at which
Expand All @@ -44,24 +50,29 @@ type RelTimeMagnitude struct {
DivBy time.Duration
}

var defaultMagnitudes = []RelTimeMagnitude{
{time.Second, "now", time.Second},
{2 * time.Second, "1 second %s", 1},
{time.Minute, "%d seconds %s", time.Second},
{2 * time.Minute, "1 minute %s", 1},
{time.Hour, "%d minutes %s", time.Minute},
{2 * time.Hour, "1 hour %s", 1},
{Day, "%d hours %s", time.Hour},
{2 * Day, "1 day %s", 1},
{Week, "%d days %s", Day},
{2 * Week, "1 week %s", 1},
{Month, "%d weeks %s", Week},
{2 * Month, "1 month %s", 1},
{Year, "%d months %s", Month},
{18 * Month, "1 year %s", 1},
{2 * Year, "2 years %s", 1},
{LongTime, "%d years %s", Year},
{math.MaxInt64, "a long while %s", 1},
var defaultMagnitudes = []RelTimeMagnitude{}

// UpdateMagnitudes to current local ruleset
func UpdateMagnitudes() {
defaultMagnitudes = []RelTimeMagnitude{
{time.Second, GetRuleset().Mags.Now, time.Second},
{2 * time.Second, GetRuleset().Mags.Second + " %s", 1},
{time.Minute, GetRuleset().Mags.Seconds + " %s", time.Second},
{2 * time.Minute, GetRuleset().Mags.Minute + " %s", 1},
{time.Hour, GetRuleset().Mags.Minutes + " %s", time.Minute},
{2 * time.Hour, GetRuleset().Mags.Hour + " %s", 1},
{Day, GetRuleset().Mags.Hours + " %s", time.Hour},
{2 * Day, GetRuleset().Mags.Day + " %s", 1},
{Week, GetRuleset().Mags.Days + " %s", Day},
{2 * Week, GetRuleset().Mags.Week + " %s", 1},
{Month, GetRuleset().Mags.Weeks + " %s", Week},
{2 * Month, GetRuleset().Mags.Month + " %s", 1},
{Year, GetRuleset().Mags.Months + " %s", Month},
{18 * Month, GetRuleset().Mags.Year + " %s", 1},
{2 * Year, "2" + GetRuleset().Mags.Years[2:] + " %s", 1},
{LongTime, GetRuleset().Mags.Years + " %s", Year},
{math.MaxInt64, GetRuleset().Mags.Longtime + " %s", 1},
}
}

// RelTime formats a time into a relative string.
Expand Down