@@ -298,6 +298,18 @@ func (l *YaLocalizer) GetJSONByCompositeKeyAndLang(
298298 key string ,
299299 lang string ,
300300) ([]byte , yaerrors.Error ) {
301+ if l .data [lang ] == nil {
302+ if l .fallbackLang != "" && lang != l .fallbackLang {
303+ lang = l .fallbackLang
304+ } else {
305+ return nil , yaerrors .FromError (
306+ http .StatusNotFound ,
307+ ErrInvalidLanguage ,
308+ fmt .Sprintf ("Language '%s' not found" , lang ),
309+ )
310+ }
311+ }
312+
301313 value , err := l .data [lang ].retriveJSONByCompositeKey (key )
302314 if err != nil {
303315 if l .fallbackLang != "" && lang != l .fallbackLang {
@@ -325,6 +337,18 @@ func (l *YaLocalizer) GetValueByCompositeKeyAndLang(
325337 key string ,
326338 lang string ,
327339) (string , yaerrors.Error ) {
340+ if l .data [lang ] == nil {
341+ if l .fallbackLang != "" && lang != l .fallbackLang {
342+ lang = l .fallbackLang
343+ } else {
344+ return "" , yaerrors .FromError (
345+ http .StatusNotFound ,
346+ ErrInvalidLanguage ,
347+ fmt .Sprintf ("Language '%s' not found" , lang ),
348+ )
349+ }
350+ }
351+
328352 value , err := l .data [lang ].retriveValueByCompositeKey (key )
329353 if err != nil {
330354 if l .fallbackLang != "" && lang != l .fallbackLang {
@@ -526,7 +550,7 @@ func (l *YaLocalizer) loadFolder(fileSystem fs.FS, compositeKey string) yaerrors
526550}
527551
528552func (l * YaLocalizer ) processJSONFile (data []byte , lang , compositeKey string ) yaerrors.Error {
529- var locales map [string ]string
553+ var locales map [string ]json. RawMessage
530554
531555 err := json .Unmarshal (data , & locales )
532556 if err != nil {
@@ -537,31 +561,95 @@ func (l *YaLocalizer) processJSONFile(data []byte, lang, compositeKey string) ya
537561 )
538562 }
539563
540- for key , value := range locales {
541- fullKey := key
542-
543- if compositeKey != "" {
544- fullKey = compositeKey + Separator + key
564+ for key , rawValue := range locales {
565+ if key == "" {
566+ return yaerrors .FromError (
567+ http .StatusTeapot ,
568+ ErrInvalidTranslation ,
569+ fmt .Sprintf ("Empty translation key at path '%s'" , compositeKey ),
570+ )
545571 }
546572
547- err := l .insertByCompositeKeyAndLang (fullKey , lang , value )
548- if err != nil {
549- return err .Wrap (fmt .Sprintf ("Failed to insert locale at key '%s'" , fullKey ))
573+ fullKey := l .joinCompositeKeys (compositeKey , key )
574+
575+ yaErr := l .processJSONNode (rawValue , lang , fullKey )
576+ if yaErr != nil {
577+ return yaErr .Wrap (fmt .Sprintf ("Failed to process JSON node at key '%s'" , fullKey ))
550578 }
551579 }
552580
553581 return nil
554582}
555583
584+ func (l * YaLocalizer ) processJSONNode (
585+ rawValue json.RawMessage ,
586+ lang , fullKey string ,
587+ ) yaerrors.Error {
588+ var value string
589+ if err := json .Unmarshal (rawValue , & value ); err == nil {
590+ yaErr := l .insertByCompositeKeyAndLang (fullKey , lang , value )
591+ if yaErr != nil {
592+ return yaErr .Wrap (fmt .Sprintf ("Failed to insert locale at key '%s'" , fullKey ))
593+ }
594+
595+ return nil
596+ }
597+
598+ var block map [string ]json.RawMessage
599+ if err := json .Unmarshal (rawValue , & block ); err == nil {
600+ for key , subRawValue := range block {
601+ if key == "" {
602+ return yaerrors .FromError (
603+ http .StatusTeapot ,
604+ ErrInvalidTranslation ,
605+ fmt .Sprintf ("Empty translation key at path '%s'" , fullKey ),
606+ )
607+ }
608+
609+ subKey := l .joinCompositeKeys (fullKey , key )
610+
611+ yaErr := l .processJSONNode (subRawValue , lang , subKey )
612+ if yaErr != nil {
613+ return yaErr .Wrap (fmt .Sprintf ("Failed to process JSON block at key '%s'" , subKey ))
614+ }
615+ }
616+
617+ return nil
618+ }
619+
620+ return yaerrors .FromError (
621+ http .StatusTeapot ,
622+ ErrInvalidTranslation ,
623+ fmt .Sprintf (
624+ "Invalid translation value at key '%s'; expected string or JSON object" ,
625+ fullKey ,
626+ ),
627+ )
628+ }
629+
630+ func (l * YaLocalizer ) joinCompositeKeys (prefix , key string ) string {
631+ if prefix == "" {
632+ return key
633+ }
634+
635+ return prefix + Separator + key
636+ }
637+
556638func (l * YaLocalizer ) insertByCompositeKeyAndLang (key , lang , value string ) yaerrors.Error {
557- if _ , ok := l .data [lang ]; ! ok {
558- keyPart := strings .SplitN (key , Separator , keySplitMaxParts )
639+ if key == "" {
640+ return yaerrors .FromError (
641+ http .StatusTeapot ,
642+ ErrInvalidTranslation ,
643+ "Empty translation key is not allowed" ,
644+ )
645+ }
559646
560- if len (keyPart ) == keySplitMaxParts {
647+ if _ , ok := l .data [lang ]; ! ok {
648+ if lang == "" {
561649 return yaerrors .FromError (
562650 http .StatusTeapot ,
563651 ErrInvalidLanguage ,
564- "New languages must be populated top-to-bottom " ,
652+ "Language tag cannot be empty " ,
565653 )
566654 }
567655
0 commit comments