-
Notifications
You must be signed in to change notification settings - Fork 20
/
join.go
133 lines (118 loc) · 2.62 KB
/
join.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package strings
// The so-called spoken language join here works well for some Western
// languages. PRs for other languages are welcome, but do note that
// implementation for some languages will be less straightforward than the ones
// in use here.
import (
"strings"
)
// Language is a spoken Language.
type Language int
// Available spoken lanaguges.
const (
DE Language = iota
DK
EN
ES
FR
IT
NO
PT
SE
)
// String returns the English name of the [Language] code.
func (l Language) String() string {
return map[Language]string{
DE: "German",
DK: "Danish",
EN: "English",
ES: "Spanish",
FR: "French",
IT: "Italian",
NO: "Norwegian",
PT: "Portuguese",
SE: "Swedish",
}[l]
}
func (l Language) conjuction() string {
switch l {
case DE:
return "und"
case DK:
return "og"
case EN:
return "and"
case ES:
return "y"
case FR:
return "et"
case NO:
return "og"
case IT:
return "e"
case PT:
return "e"
case SE:
return "och"
default:
return ""
}
}
func (l Language) separator() string {
switch l {
case DE, DK, EN, ES, FR, NO, IT, PT, SE:
return ", "
default:
return " "
}
}
// EnglishJoin joins a slice of strings with commas and the "and" conjugation
// before the final item. The Oxford comma can optionally be applied.
//
// Example:
//
// str := EnglishJoin([]string{"meow", "purr", "raow"}, true)
// fmt.Println(str) // meow, purr, and raow
func EnglishJoin(words []string, oxfordComma bool) string {
return spokenLangJoin(words, EN, oxfordComma)
}
// SpokenLangaugeJoin joins a slice of strings with commas and a conjuction
// before the final item. You may specify the language with [Language].
//
// If you are using English and need the Oxford Comma, use [EnglishJoin].
//
// Example:
//
// str := SpokenLanguageJoin([]string{"eins", "zwei", "drei"}, DE)
// fmt.Println(str) // eins, zwei und drei
func SpokenLanguageJoin(words []string, language Language) string {
return spokenLangJoin(words, language, false)
}
func spokenLangJoin(words []string, language Language, oxfordComma bool) string {
conjuction := language.conjuction() + " "
separator := language.separator()
b := strings.Builder{}
for i, word := range words {
if word == "" {
continue
}
if i == 0 {
b.WriteString(word)
continue
}
// Is this the final word?
if len(words) > 1 && i == len(words)-1 {
// Apply the Oxford comma if requested as long as the language is
// English.
if language == EN && oxfordComma && i > 1 {
b.WriteString(separator)
} else {
b.WriteRune(' ')
}
b.WriteString(conjuction + word)
continue
}
b.WriteString(separator + word)
}
return b.String()
}