cli/pkg/i18n/mutate.go
Snider b2448fa5f2 refactor(i18n): extract JSON flattening to mutate.go
Move flatten and flattenWithGrammar functions to dedicated file.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 14:54:03 +00:00

133 lines
3.7 KiB
Go

// Package i18n provides internationalization for the CLI.
package i18n
import "strings"
// flatten recursively flattens nested maps into dot-notation keys.
func flatten(prefix string, data map[string]any, out map[string]Message) {
flattenWithGrammar(prefix, data, out, nil)
}
// flattenWithGrammar recursively flattens nested maps and extracts grammar data.
func flattenWithGrammar(prefix string, data map[string]any, out map[string]Message, grammar *GrammarData) {
for key, value := range data {
fullKey := key
if prefix != "" {
fullKey = prefix + "." + key
}
switch v := value.(type) {
case string:
out[fullKey] = Message{Text: v}
case map[string]any:
// Check if this is a verb form object
// Grammar data lives under "gram.*" (a nod to Gram - grandmother)
if grammar != nil && isVerbFormObject(v) {
verbName := key
if strings.HasPrefix(fullKey, "gram.verb.") {
verbName = strings.TrimPrefix(fullKey, "gram.verb.")
}
forms := VerbForms{}
if base, ok := v["base"].(string); ok {
_ = base // base form stored but not used in VerbForms
}
if past, ok := v["past"].(string); ok {
forms.Past = past
}
if gerund, ok := v["gerund"].(string); ok {
forms.Gerund = gerund
}
grammar.Verbs[strings.ToLower(verbName)] = forms
continue
}
// Check if this is a noun form object
if grammar != nil && isNounFormObject(v) {
nounName := key
if strings.HasPrefix(fullKey, "gram.noun.") {
nounName = strings.TrimPrefix(fullKey, "gram.noun.")
}
forms := NounForms{}
if one, ok := v["one"].(string); ok {
forms.One = one
}
if other, ok := v["other"].(string); ok {
forms.Other = other
}
if gender, ok := v["gender"].(string); ok {
forms.Gender = gender
}
grammar.Nouns[strings.ToLower(nounName)] = forms
continue
}
// Check if this is an article object
if grammar != nil && fullKey == "gram.article" {
if indef, ok := v["indefinite"].(map[string]any); ok {
if def, ok := indef["default"].(string); ok {
grammar.Articles.IndefiniteDefault = def
}
if vowel, ok := indef["vowel"].(string); ok {
grammar.Articles.IndefiniteVowel = vowel
}
}
if def, ok := v["definite"].(string); ok {
grammar.Articles.Definite = def
}
continue
}
// Check if this is a punctuation rules object
if grammar != nil && fullKey == "gram.punct" {
if label, ok := v["label"].(string); ok {
grammar.Punct.LabelSuffix = label
}
if progress, ok := v["progress"].(string); ok {
grammar.Punct.ProgressSuffix = progress
}
continue
}
// Check if this is a base word in gram.word.*
if grammar != nil && strings.HasPrefix(fullKey, "gram.word.") {
wordKey := strings.TrimPrefix(fullKey, "gram.word.")
// v could be a string or a nested object
if str, ok := value.(string); ok {
if grammar.Words == nil {
grammar.Words = make(map[string]string)
}
grammar.Words[strings.ToLower(wordKey)] = str
}
continue
}
// Check if this is a plural object (has CLDR plural category keys)
if isPluralObject(v) {
msg := Message{}
if zero, ok := v["zero"].(string); ok {
msg.Zero = zero
}
if one, ok := v["one"].(string); ok {
msg.One = one
}
if two, ok := v["two"].(string); ok {
msg.Two = two
}
if few, ok := v["few"].(string); ok {
msg.Few = few
}
if many, ok := v["many"].(string); ok {
msg.Many = many
}
if other, ok := v["other"].(string); ok {
msg.Other = other
}
out[fullKey] = msg
} else {
// Recurse into nested object
flattenWithGrammar(fullKey, v, out, grammar)
}
}
}
}