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>
This commit is contained in:
parent
c331c29c05
commit
b2448fa5f2
2 changed files with 133 additions and 131 deletions
131
pkg/i18n/i18n.go
131
pkg/i18n/i18n.go
|
|
@ -185,137 +185,6 @@ func _(messageID string, args ...any) string {
|
|||
return messageID
|
||||
}
|
||||
|
||||
// --- JSON parsing helpers ---
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func detectLanguage(supported []language.Tag) string {
|
||||
langEnv := os.Getenv("LANG")
|
||||
if langEnv == "" {
|
||||
|
|
|
|||
133
pkg/i18n/mutate.go
Normal file
133
pkg/i18n/mutate.go
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
// 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue