7 "github.com/go-playground/locales"
8 "github.com/go-playground/locales/en"
9 "github.com/go-playground/locales/en_CA"
10 "github.com/go-playground/locales/nl"
14 // - Run "go test" to run tests
15 // - Run "gocov test | gocov report" to report on test converage by file
16 // - Run "gocov test | gocov annotate -" to report on all code and functions, those ,marked with "MISS" were never called
20 // -- may be a good idea to change to output path to somewherelike /tmp
21 // go test -coverprofile cover.out && go tool cover -html=cover.out -o cover.html
24 func TestBasicTranslation(t *testing.T) {
28 en, found := uni.GetTranslator("en") // or fallback if fails to find 'en'
30 t.Fatalf("Expected '%t' Got '%t'", true, found)
33 translations := []struct {
52 trans: "{0} to the {1}.",
57 trans: "Welcome {0} to the {1}",
68 expected: &ErrConflictingTranslation{locale: en.Locale(), key: "test_trans", text: "{0}{1}"},
74 expected: &ErrConflictingTranslation{locale: en.Locale(), key: -1, text: "{0}{1}"},
79 trans: "Welcome {0} to the {1}.",
85 for _, tt := range translations {
87 err := en.Add(tt.key, tt.trans, tt.override)
88 if err != tt.expected {
89 if !tt.expectedError {
90 t.Errorf("Expected '%s' Got '%s'", tt.expected, err)
92 if err.Error() != tt.expected.Error() {
93 t.Errorf("Expected '%s' Got '%s'", tt.expected.Error(), err.Error())
107 params: []string{"Joeybloggs", "The Test"},
108 expected: "Welcome Joeybloggs to the The Test.",
112 params: []string{"Joeybloggs", "The Test"},
113 expected: "Joeybloggs to the The Test.",
117 params: []string{"Joeybloggs", "The Test"},
118 expected: "Welcome Joeybloggs to the The Test",
122 params: []string{"Joeybloggs", "The Test"},
123 expected: "JoeybloggsThe Test",
127 key: "non-existant-key",
128 params: []string{"Joeybloggs", "The Test"},
134 for _, tt := range tests {
135 s, err := en.T(tt.key, tt.params...)
136 if s != tt.expected {
137 if !tt.expectedError && err != ErrUnknowTranslation {
138 t.Errorf("Expected '%s' Got '%s'", tt.expected, s)
144 func TestCardinalTranslation(t *testing.T) {
148 en, found := uni.GetTranslator("en")
150 t.Fatalf("Expected '%t' Got '%t'", true, found)
153 translations := []struct {
156 rule locales.PluralRule
163 key: "cardinal_test",
164 trans: "You have a day left.",
165 rule: locales.PluralRuleOne,
166 expected: &ErrCardinalTranslation{text: fmt.Sprintf("error: parameter '%s' not found, may want to use 'Add' instead of 'AddCardinal'. locale: '%s' key: '%v' text: '%s'", paramZero, en.Locale(), "cardinal_test", "You have a day left.")},
171 key: "cardinal_test",
172 trans: "You have a day left few.",
173 rule: locales.PluralRuleFew,
174 expected: &ErrCardinalTranslation{text: fmt.Sprintf("error: cardinal plural rule '%s' does not exist for locale '%s' key: '%s' text: '%s'", locales.PluralRuleFew, en.Locale(), "cardinal_test", "You have a day left few.")},
178 key: "cardinal_test",
179 trans: "You have {0} day",
180 rule: locales.PluralRuleOne,
184 key: "cardinal_test",
185 trans: "You have {0} days left.",
186 rule: locales.PluralRuleOther,
190 key: "cardinal_test",
191 trans: "You have {0} days left.",
192 rule: locales.PluralRuleOther,
193 expected: &ErrConflictingTranslation{locale: en.Locale(), key: "cardinal_test", rule: locales.PluralRuleOther, text: "You have {0} days left."},
197 key: "cardinal_test",
198 trans: "You have {0} day left.",
199 rule: locales.PluralRuleOne,
205 for _, tt := range translations {
207 err := en.AddCardinal(tt.key, tt.trans, tt.rule, tt.override)
208 if err != tt.expected {
209 if !tt.expectedError || err.Error() != tt.expected.Error() {
210 t.Errorf("Expected '<nil>' Got '%s'", err)
224 key: "cardinal_test",
227 param: string(en.FmtNumber(1, 0)),
228 expected: "You have 1 day left.",
230 // bad translation key
235 param: string(en.FmtNumber(1, 0)),
241 for _, tt := range tests {
243 s, err := en.C(tt.key, tt.num, tt.digits, tt.param)
245 if !tt.expectedError && err != ErrUnknowTranslation {
246 t.Errorf("Expected '<nil>' Got '%s'", err)
250 if s != tt.expected {
251 t.Errorf("Expected '%s' Got '%s'", tt.expected, s)
256 func TestOrdinalTranslation(t *testing.T) {
260 en, found := uni.GetTranslator("en")
262 t.Fatalf("Expected '%t' Got '%t'", true, found)
265 translations := []struct {
268 rule locales.PluralRule
277 rule: locales.PluralRuleOne,
278 expected: &ErrOrdinalTranslation{text: fmt.Sprintf("error: parameter '%s' not found, may want to use 'Add' instead of 'AddOrdinal'. locale: '%s' key: '%v' text: '%s'", paramZero, en.Locale(), "day", "st")},
285 rule: locales.PluralRuleMany,
286 expected: &ErrOrdinalTranslation{text: fmt.Sprintf("error: ordinal plural rule '%s' does not exist for locale '%s' key: '%s' text: '%s'", locales.PluralRuleMany, en.Locale(), "day", "st")},
292 rule: locales.PluralRuleOne,
298 rule: locales.PluralRuleTwo,
304 rule: locales.PluralRuleFew,
310 rule: locales.PluralRuleOther,
317 rule: locales.PluralRuleOther,
318 expected: &ErrConflictingTranslation{locale: en.Locale(), key: "day", rule: locales.PluralRuleOther, text: "{0}th"},
324 rule: locales.PluralRuleOne,
330 for _, tt := range translations {
332 err := en.AddOrdinal(tt.key, tt.trans, tt.rule, tt.override)
333 if err != tt.expected {
334 if !tt.expectedError || err.Error() != tt.expected.Error() {
335 t.Errorf("Expected '<nil>' Got '%s'", err)
352 param: string(en.FmtNumber(1, 0)),
359 param: string(en.FmtNumber(2, 0)),
366 param: string(en.FmtNumber(3, 0)),
373 param: string(en.FmtNumber(4, 0)),
380 param: string(en.FmtNumber(10258.43, 0)),
381 expected: "10,258th",
388 param: string(en.FmtNumber(10258.43, 0)),
394 for _, tt := range tests {
396 s, err := en.O(tt.key, tt.num, tt.digits, tt.param)
398 if !tt.expectedError && err != ErrUnknowTranslation {
399 t.Errorf("Expected '<nil>' Got '%s'", err)
403 if s != tt.expected {
404 t.Errorf("Expected '%s' Got '%s'", tt.expected, s)
409 func TestRangeTranslation(t *testing.T) {
415 nl, found := uni.GetTranslator("nl")
417 t.Fatalf("Expected '%t' Got '%t'", true, found)
420 translations := []struct {
423 rule locales.PluralRule
431 trans: "er -{1} dag vertrokken",
432 rule: locales.PluralRuleOne,
433 expected: &ErrRangeTranslation{text: fmt.Sprintf("error: parameter '%s' not found, are you sure you're adding a Range Translation? locale: '%s' key: '%s' text: '%s'", paramZero, nl.Locale(), "day", "er -{1} dag vertrokken")},
439 trans: "er {0}- dag vertrokken",
440 rule: locales.PluralRuleMany,
441 expected: &ErrRangeTranslation{text: fmt.Sprintf("error: range plural rule '%s' does not exist for locale '%s' key: '%s' text: '%s'", locales.PluralRuleMany, nl.Locale(), "day", "er {0}- dag vertrokken")},
447 trans: "er {0}- dag vertrokken",
448 rule: locales.PluralRuleOne,
449 expected: &ErrRangeTranslation{text: fmt.Sprintf("error: parameter '%s' not found, a Range Translation requires two parameters. locale: '%s' key: '%s' text: '%s'", paramOne, nl.Locale(), "day", "er {0}- dag vertrokken")},
454 trans: "er {0}-{1} dag",
455 rule: locales.PluralRuleOne,
460 trans: "er zijn {0}-{1} dagen over",
461 rule: locales.PluralRuleOther,
467 trans: "er zijn {0}-{1} dagen over",
468 rule: locales.PluralRuleOther,
469 expected: &ErrConflictingTranslation{locale: nl.Locale(), key: "day", rule: locales.PluralRuleOther, text: "er zijn {0}-{1} dagen over"},
474 trans: "er {0}-{1} dag vertrokken",
475 rule: locales.PluralRuleOne,
481 for _, tt := range translations {
483 err := nl.AddRange(tt.key, tt.trans, tt.rule, tt.override)
484 if err != tt.expected {
485 if !tt.expectedError || err.Error() != tt.expected.Error() {
486 t.Errorf("Expected '%#v' Got '%s'", tt.expected, err)
508 param1: string(nl.FmtNumber(1, 0)),
509 param2: string(nl.FmtNumber(2, 0)),
510 expected: "er zijn 1-2 dagen over",
518 param1: string(nl.FmtNumber(0, 0)),
519 param2: string(nl.FmtNumber(1, 0)),
520 expected: "er 0-1 dag vertrokken",
528 param1: string(nl.FmtNumber(0, 0)),
529 param2: string(nl.FmtNumber(2, 0)),
530 expected: "er zijn 0-2 dagen over",
532 // bad translations from here
539 param1: string(nl.FmtNumber(0, 0)),
540 param2: string(nl.FmtNumber(2, 0)),
546 for _, tt := range tests {
548 s, err := nl.R(tt.key, tt.num1, tt.digits1, tt.num2, tt.digits2, tt.param1, tt.param2)
550 if !tt.expectedError && err != ErrUnknowTranslation {
551 t.Errorf("Expected '<nil>' Got '%s'", err)
555 if s != tt.expected {
556 t.Errorf("Expected '%s' Got '%s'", tt.expected, s)
561 func TestFallbackTranslator(t *testing.T) {
565 en, found := uni.GetTranslator("en")
567 t.Fatalf("Expected '%t' Got '%t'", true, found)
570 if en.Locale() != "en" {
571 t.Errorf("Expected '%s' Got '%s'", "en", en.Locale())
574 fallback, _ := uni.GetTranslator("nl")
575 if fallback.Locale() != "en" {
576 t.Errorf("Expected '%s' Got '%s'", "en", fallback.Locale())
579 en, _ = uni.FindTranslator("nl", "en")
580 if en.Locale() != "en" {
581 t.Errorf("Expected '%s' Got '%s'", "en", en.Locale())
584 fallback, _ = uni.FindTranslator("nl")
585 if fallback.Locale() != "en" {
586 t.Errorf("Expected '%s' Got '%s'", "en", fallback.Locale())
590 func TestAddTranslator(t *testing.T) {
597 trans locales.Translator
609 expected: &ErrExistingTranslator{locale: n.Locale()},
615 expected: &ErrExistingTranslator{locale: e.Locale()},
626 for _, tt := range tests {
628 err := uni.AddTranslator(tt.trans, tt.override)
629 if err != tt.expected {
630 if !tt.expectedError || err.Error() != tt.expected.Error() {
631 t.Errorf("Expected '%s' Got '%s'", tt.expected, err)
637 func TestVerifyTranslations(t *testing.T) {
643 loc, _ := uni.GetTranslator("nl")
644 if loc.Locale() != "nl" {
645 t.Errorf("Expected '%s' Got '%s'", "nl", loc.Locale())
650 err := loc.AddCardinal("day", "je {0} dag hebben verlaten", locales.PluralRuleOne, false)
652 t.Fatalf("Expected '<nil>' Got '%s'", err)
655 // fail cardinal rules
656 expected := &ErrMissingPluralTranslation{locale: loc.Locale(), translationType: "plural", rule: locales.PluralRuleOther, key: "day"}
657 err = loc.VerifyTranslations()
658 if err == nil || err.Error() != expected.Error() {
659 t.Errorf("Expected '%s' Got '%s'", expected, err)
663 err = loc.AddCardinal("day", "je {0} dagen hebben verlaten", locales.PluralRuleOther, false)
665 t.Fatalf("Expected '<nil>' Got '%s'", err)
668 err = loc.VerifyTranslations()
670 t.Fatalf("Expected '<nil>' Got '%s'", err)
674 err = loc.AddRange("day", "je {0}-{1} dagen hebben verlaten", locales.PluralRuleOther, false)
676 t.Fatalf("Expected '<nil>' Got '%s'", err)
680 expected = &ErrMissingPluralTranslation{locale: loc.Locale(), translationType: "range", rule: locales.PluralRuleOne, key: "day"}
681 err = loc.VerifyTranslations()
682 if err == nil || err.Error() != expected.Error() {
683 t.Errorf("Expected '%s' Got '%s'", expected, err)
687 err = loc.AddRange("day", "je {0}-{1} dag hebben verlaten", locales.PluralRuleOne, false)
689 t.Fatalf("Expected '<nil>' Got '%s'", err)
692 err = loc.VerifyTranslations()
694 t.Fatalf("Expected '<nil>' Got '%s'", err)
697 // ok so 'nl' aka dutch, ony has one plural rule for ordinals, so going to switch to english from here which has 4
699 err = uni.AddTranslator(en.New(), false)
701 t.Fatalf("Expected '<nil>' Got '%s'", err)
704 loc, _ = uni.GetTranslator("en")
705 if loc.Locale() != "en" {
706 t.Errorf("Expected '%s' Got '%s'", "en", loc.Locale())
711 err = loc.AddOrdinal("day", "{0}st", locales.PluralRuleOne, false)
713 t.Fatalf("Expected '<nil>' Got '%s'", err)
716 err = loc.AddOrdinal("day", "{0}rd", locales.PluralRuleFew, false)
718 t.Fatalf("Expected '<nil>' Got '%s'", err)
721 err = loc.AddOrdinal("day", "{0}th", locales.PluralRuleOther, false)
723 t.Fatalf("Expected '<nil>' Got '%s'", err)
726 // fail ordinal rules
727 expected = &ErrMissingPluralTranslation{locale: loc.Locale(), translationType: "ordinal", rule: locales.PluralRuleTwo, key: "day"}
728 err = loc.VerifyTranslations()
729 if err == nil || err.Error() != expected.Error() {
730 t.Errorf("Expected '%s' Got '%s'", expected, err)
735 err = loc.AddOrdinal("day", "{0}nd", locales.PluralRuleTwo, false)
737 t.Fatalf("Expected '<nil>' Got '%s'", err)
740 err = loc.VerifyTranslations()
742 t.Fatalf("Expected '<nil>' Got '%s'", err)
746 func TestVerifyTranslationsWithNonStringKeys(t *testing.T) {
752 loc, _ := uni.GetTranslator("nl")
753 if loc.Locale() != "nl" {
754 t.Errorf("Expected '%s' Got '%s'", "nl", loc.Locale())
759 err := loc.AddCardinal(-1, "je {0} dag hebben verlaten", locales.PluralRuleOne, false)
761 t.Fatalf("Expected '<nil>' Got '%s'", err)
764 // fail cardinal rules
765 expected := &ErrMissingPluralTranslation{locale: loc.Locale(), translationType: "plural", rule: locales.PluralRuleOther, key: -1}
766 err = loc.VerifyTranslations()
767 if err == nil || err.Error() != expected.Error() {
768 t.Errorf("Expected '%s' Got '%s'", expected, err)
772 func TestGetFallback(t *testing.T) {
780 trans := uni.GetFallback()
784 if trans.Locale() != expected {
785 t.Errorf("Expected '%s' Got '%s'", expected, trans.Locale())
789 func TestVerifyUTTranslations(t *testing.T) {
793 en, found := uni.GetTranslator("en")
795 t.Fatalf("Expected '%t' Got '%t'", true, found)
798 translations := []struct {
801 rule locales.PluralRule
809 rule: locales.PluralRuleOne,
815 rule: locales.PluralRuleTwo,
821 rule: locales.PluralRuleFew,
824 // intentionally leaving out plural other
828 // rule: locales.PluralRuleOther,
833 for _, tt := range translations {
835 err := en.AddOrdinal(tt.key, tt.trans, tt.rule, tt.override)
836 if err != tt.expected {
837 if !tt.expectedError || err.Error() != tt.expected.Error() {
838 t.Errorf("Expected '<nil>' Got '%s'", err)
843 expected := "error: missing 'ordinal' plural rule 'Other' for translation with key 'day' and locale 'en'"
844 err := uni.VerifyTranslations()
845 if err == nil || err.Error() != expected {
846 t.Fatalf("Expected '%s' Got '%s'", expected, err)
849 err = en.AddOrdinal("day", "{0}th", locales.PluralRuleOther, false)
851 t.Fatalf("Expected '%v' Got '%s'", nil, err)
854 err = uni.VerifyTranslations()
856 t.Fatalf("Expected '%v' Got '%s'", nil, err)