cli/pkg/i18n/language_test.go
Snider 46f6d4c5fe feat(i18n): add Phase 4 extended language support
Fluent Intent Builder API:
- I("core.delete").For(S("file", path)).Question()
- I("core.delete").With(subject).Compose()
- Convenience methods: Question(), Success(), Failure(), Meta(), IsDangerous()

Formality Levels (for Sie/du, vous/tu languages):
- FormalityNeutral, FormalityInformal, FormalityFormal constants
- Subject.Formal(), Subject.Informal(), Subject.Formality()
- Service.SetFormality(), Service.Formality()
- Package-level SetFormality()

CLDR Plural Categories:
- PluralZero, PluralOne, PluralTwo, PluralFew, PluralMany, PluralOther
- Language-specific plural rules: English, German, French, Spanish, Russian, Polish, Arabic, Chinese, Japanese, Korean
- Message.ForCategory() for proper plural selection
- Service.PluralCategory() for getting category by count

RTL Text Direction Support:
- TextDirection type (DirLTR, DirRTL)
- IsRTLLanguage() for language detection
- Service.Direction(), Service.IsRTL()
- Package-level Direction(), IsRTL()

GrammaticalGender type:
- GenderNeuter, GenderMasculine, GenderFeminine, GenderCommon
- For future gender agreement in gendered languages

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 12:55:41 +00:00

172 lines
3.8 KiB
Go

package i18n
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestFormality_String(t *testing.T) {
tests := []struct {
f Formality
expected string
}{
{FormalityNeutral, "neutral"},
{FormalityInformal, "informal"},
{FormalityFormal, "formal"},
{Formality(99), "neutral"}, // Unknown defaults to neutral
}
for _, tt := range tests {
assert.Equal(t, tt.expected, tt.f.String())
}
}
func TestTextDirection_String(t *testing.T) {
assert.Equal(t, "ltr", DirLTR.String())
assert.Equal(t, "rtl", DirRTL.String())
}
func TestPluralCategory_String(t *testing.T) {
tests := []struct {
cat PluralCategory
expected string
}{
{PluralZero, "zero"},
{PluralOne, "one"},
{PluralTwo, "two"},
{PluralFew, "few"},
{PluralMany, "many"},
{PluralOther, "other"},
}
for _, tt := range tests {
assert.Equal(t, tt.expected, tt.cat.String())
}
}
func TestGrammaticalGender_String(t *testing.T) {
tests := []struct {
g GrammaticalGender
expected string
}{
{GenderNeuter, "neuter"},
{GenderMasculine, "masculine"},
{GenderFeminine, "feminine"},
{GenderCommon, "common"},
}
for _, tt := range tests {
assert.Equal(t, tt.expected, tt.g.String())
}
}
func TestIsRTLLanguage(t *testing.T) {
// RTL languages
assert.True(t, IsRTLLanguage("ar"))
assert.True(t, IsRTLLanguage("ar-SA"))
assert.True(t, IsRTLLanguage("he"))
assert.True(t, IsRTLLanguage("he-IL"))
assert.True(t, IsRTLLanguage("fa"))
assert.True(t, IsRTLLanguage("ur"))
// LTR languages
assert.False(t, IsRTLLanguage("en"))
assert.False(t, IsRTLLanguage("en-GB"))
assert.False(t, IsRTLLanguage("de"))
assert.False(t, IsRTLLanguage("fr"))
assert.False(t, IsRTLLanguage("zh"))
}
func TestPluralRuleEnglish(t *testing.T) {
tests := []struct {
n int
expected PluralCategory
}{
{0, PluralOther},
{1, PluralOne},
{2, PluralOther},
{5, PluralOther},
{100, PluralOther},
}
for _, tt := range tests {
assert.Equal(t, tt.expected, pluralRuleEnglish(tt.n), "count=%d", tt.n)
}
}
func TestPluralRuleFrench(t *testing.T) {
// French uses singular for 0 and 1
assert.Equal(t, PluralOne, pluralRuleFrench(0))
assert.Equal(t, PluralOne, pluralRuleFrench(1))
assert.Equal(t, PluralOther, pluralRuleFrench(2))
}
func TestPluralRuleRussian(t *testing.T) {
tests := []struct {
n int
expected PluralCategory
}{
{1, PluralOne},
{2, PluralFew},
{3, PluralFew},
{4, PluralFew},
{5, PluralMany},
{11, PluralMany},
{12, PluralMany},
{21, PluralOne},
{22, PluralFew},
{25, PluralMany},
}
for _, tt := range tests {
assert.Equal(t, tt.expected, pluralRuleRussian(tt.n), "count=%d", tt.n)
}
}
func TestPluralRuleArabic(t *testing.T) {
tests := []struct {
n int
expected PluralCategory
}{
{0, PluralZero},
{1, PluralOne},
{2, PluralTwo},
{3, PluralFew},
{10, PluralFew},
{11, PluralMany},
{99, PluralMany},
{100, PluralOther},
}
for _, tt := range tests {
assert.Equal(t, tt.expected, pluralRuleArabic(tt.n), "count=%d", tt.n)
}
}
func TestPluralRuleChinese(t *testing.T) {
// Chinese has no plural distinction
assert.Equal(t, PluralOther, pluralRuleChinese(0))
assert.Equal(t, PluralOther, pluralRuleChinese(1))
assert.Equal(t, PluralOther, pluralRuleChinese(100))
}
func TestGetPluralRule(t *testing.T) {
// Known languages
rule := GetPluralRule("en-GB")
assert.Equal(t, PluralOne, rule(1))
rule = GetPluralRule("ru")
assert.Equal(t, PluralFew, rule(2))
// Unknown language falls back to English
rule = GetPluralRule("xx-unknown")
assert.Equal(t, PluralOne, rule(1))
assert.Equal(t, PluralOther, rule(2))
}
func TestGetPluralCategory(t *testing.T) {
assert.Equal(t, PluralOne, GetPluralCategory("en", 1))
assert.Equal(t, PluralOther, GetPluralCategory("en", 5))
assert.Equal(t, PluralFew, GetPluralCategory("ru", 3))
}