diff --git a/service.go b/service.go index 47cdbe6..80e3730 100644 --- a/service.go +++ b/service.go @@ -344,14 +344,13 @@ func (s *Service) resolveWithFallback(messageID string, data any) string { } func (s *Service) tryResolve(lang, key string, data any) string { - formality := s.getEffectiveFormality(data) - if formality != FormalityNeutral { - formalityKey := key + "._" + formality.String() - if text := s.resolveMessage(lang, formalityKey, data); text != "" { + context, formality := s.getEffectiveContextAndFormality(data) + for _, lookupKey := range lookupVariants(key, context, formality) { + if text := s.resolveMessage(lang, lookupKey, data); text != "" { return text } } - return s.resolveMessage(lang, key, data) + return "" } func (s *Service) resolveMessage(lang, key string, data any) string { @@ -374,6 +373,39 @@ func (s *Service) resolveMessage(lang, key string, data any) string { return text } +func (s *Service) getEffectiveContextAndFormality(data any) (string, Formality) { + if ctx, ok := data.(*TranslationContext); ok && ctx != nil { + formality := ctx.FormalityValue() + if formality == FormalityNeutral { + formality = s.formality + } + return ctx.ContextString(), formality + } + if m, ok := data.(map[string]any); ok { + var context string + if v, ok := m["Context"].(string); ok { + context = core.Trim(v) + } + if v, ok := m["Formality"]; ok { + switch f := v.(type) { + case Formality: + if f != FormalityNeutral { + return context, f + } + case string: + switch core.Lower(f) { + case "formal": + return context, FormalityFormal + case "informal": + return context, FormalityInformal + } + } + } + return context, s.formality + } + return "", s.getEffectiveFormality(data) +} + func (s *Service) getEffectiveFormality(data any) Formality { if ctx, ok := data.(*TranslationContext); ok && ctx != nil { if ctx.Formality != FormalityNeutral { @@ -403,6 +435,21 @@ func (s *Service) getEffectiveFormality(data any) Formality { return s.formality } +func lookupVariants(key, context string, formality Formality) []string { + var variants []string + if context != "" { + if formality != FormalityNeutral { + variants = append(variants, key+"._"+context+"._"+formality.String()) + } + variants = append(variants, key+"._"+context) + } + if formality != FormalityNeutral { + variants = append(variants, key+"._"+formality.String()) + } + variants = append(variants, key) + return variants +} + func (s *Service) handleMissingKey(key string, args []any) string { switch s.mode { case ModeStrict: diff --git a/service_test.go b/service_test.go index 76076c0..17f8eeb 100644 --- a/service_test.go +++ b/service_test.go @@ -202,6 +202,36 @@ func TestServiceFormality(t *testing.T) { } } +func TestServiceTranslationContext(t *testing.T) { + svc, err := New() + if err != nil { + t.Fatalf("New() failed: %v", err) + } + + svc.AddMessages("en", map[string]string{ + "direction.right._navigation": "right", + "direction.right._navigation._formal": "right, sir", + "direction.right._correctness": "correct", + "direction.right._correctness._formal": "correct, sir", + }) + + if got := svc.T("direction.right", C("navigation")); got != "right" { + t.Errorf("T(direction.right, C(navigation)) = %q, want %q", got, "right") + } + + if got := svc.T("direction.right", C("navigation").Formal()); got != "right, sir" { + t.Errorf("T(direction.right, C(navigation).Formal()) = %q, want %q", got, "right, sir") + } + + if got := svc.T("direction.right", C("correctness")); got != "correct" { + t.Errorf("T(direction.right, C(correctness)) = %q, want %q", got, "correct") + } + + if got := svc.T("direction.right", C("correctness").Formal()); got != "correct, sir" { + t.Errorf("T(direction.right, C(correctness).Formal()) = %q, want %q", got, "correct, sir") + } +} + func TestServiceDirection(t *testing.T) { svc, err := New() if err != nil {