1
- // Copyright 2017 The Hugo Authors. All rights reserved.
1
+ // Copyright 2022 The Hugo Authors. All rights reserved.
2
2
//
3
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
4
// you may not use this file except in compliance with the License.
@@ -24,54 +24,76 @@ import (
24
24
"github.com/gohugoio/hugo/common/loggers"
25
25
"github.com/gohugoio/hugo/config"
26
26
"github.com/gohugoio/hugo/helpers"
27
+ "github.com/gohugoio/hugo/langs"
27
28
28
29
"github.com/gohugoio/go-i18n/v2/i18n"
29
30
)
30
31
32
+ type translator struct {
33
+ translate func (translationID string , templateData any ) string
34
+ hasTranslation func (translationID string ) bool
35
+ }
36
+
37
+ var nopTranslator = translator {}
38
+
39
+ func (t translator ) Translate (translationID string , templateData any ) string {
40
+ if t .translate == nil {
41
+ return ""
42
+ }
43
+ return t .translate (translationID , templateData )
44
+ }
45
+
46
+ func (t translator ) HasTranslation (translationID string ) bool {
47
+ if t .hasTranslation == nil {
48
+ return false
49
+ }
50
+ return t .hasTranslation (translationID )
51
+ }
52
+
31
53
type translateFunc func (translationID string , templateData any ) string
32
54
33
55
var i18nWarningLogger = helpers .NewDistinctErrorLogger ()
34
56
35
- // Translator handles i18n translations.
36
- type Translator struct {
37
- translateFuncs map [string ]translateFunc
38
- cfg config.Provider
39
- logger loggers.Logger
57
+ // Translators handles i18n translations.
58
+ type Translators struct {
59
+ translators map [string ]langs. Translator
60
+ cfg config.Provider
61
+ logger loggers.Logger
40
62
}
41
63
42
64
// NewTranslator creates a new Translator for the given language bundle and configuration.
43
- func NewTranslator (b * i18n.Bundle , cfg config.Provider , logger loggers.Logger ) Translator {
44
- t := Translator {cfg : cfg , logger : logger , translateFuncs : make (map [string ]translateFunc )}
65
+ func NewTranslator (b * i18n.Bundle , cfg config.Provider , logger loggers.Logger ) Translators {
66
+ t := Translators {cfg : cfg , logger : logger , translators : make (map [string ]langs. Translator )}
45
67
t .initFuncs (b )
46
68
return t
47
69
}
48
70
49
- // Func gets the translate func for the given language, or for the default
71
+ // Get gets the Translator for the given language, or for the default
50
72
// configured language if not found.
51
- func (t Translator ) Func (lang string ) translateFunc {
52
- if f , ok := t . translateFuncs [lang ]; ok {
53
- return f
73
+ func (ts Translators ) Get (lang string ) langs. Translator {
74
+ if t , ok := ts . translators [lang ]; ok {
75
+ return t
54
76
}
55
- t .logger .Infof ("Translation func for language %v not found, use default." , lang )
56
- if f , ok := t . translateFuncs [ t .cfg .GetString ("defaultContentLanguage" )]; ok {
57
- return f
77
+ ts .logger .Infof ("Translation func for language %v not found, use default." , lang )
78
+ if tt , ok := ts . translators [ ts .cfg .GetString ("defaultContentLanguage" )]; ok {
79
+ return tt
58
80
}
59
81
60
- t .logger .Infoln ("i18n not initialized; if you need string translations, check that you have a bundle in /i18n that matches the site language or the default language." )
61
- return func (translationID string , args any ) string {
62
- return ""
63
- }
82
+ ts .logger .Infoln ("i18n not initialized; if you need string translations, check that you have a bundle in /i18n that matches the site language or the default language." )
83
+
84
+ return nopTranslator
64
85
}
65
86
66
- func (t Translator ) initFuncs (bndl * i18n.Bundle ) {
67
- enableMissingTranslationPlaceholders := t .cfg .GetBool ("enableMissingTranslationPlaceholders" )
87
+ func (ts Translators ) initFuncs (bndl * i18n.Bundle ) {
88
+ enableMissingTranslationPlaceholders := ts .cfg .GetBool ("enableMissingTranslationPlaceholders" )
68
89
for _ , lang := range bndl .LanguageTags () {
69
90
currentLang := lang
70
91
currentLangStr := currentLang .String ()
71
92
// This may be pt-BR; make it case insensitive.
72
93
currentLangKey := strings .ToLower (strings .TrimPrefix (currentLangStr , artificialLangTagPrefix ))
73
94
localizer := i18n .NewLocalizer (bndl , currentLangStr )
74
- t .translateFuncs [currentLangKey ] = func (translationID string , templateData any ) string {
95
+
96
+ translate := func (translationID string , templateData any ) (string , error ) {
75
97
pluralCount := getPluralCount (templateData )
76
98
77
99
if templateData != nil {
@@ -90,10 +112,12 @@ func (t Translator) initFuncs(bndl *i18n.Bundle) {
90
112
PluralCount : pluralCount ,
91
113
})
92
114
115
+ fmt .Println ("translatedLang" , translatedLang , "currentLang" , currentLang , "err" , err , "translated" , translated )
116
+
93
117
sameLang := currentLang == translatedLang
94
118
95
119
if err == nil && sameLang {
96
- return translated
120
+ return translated , nil
97
121
}
98
122
99
123
if err != nil && sameLang && translated != "" {
@@ -102,24 +126,41 @@ func (t Translator) initFuncs(bndl *i18n.Bundle) {
102
126
// but currently we get an error even if the fallback to
103
127
// "other" succeeds.
104
128
if fmt .Sprintf ("%T" , err ) == "i18n.pluralFormNotFoundError" {
105
- return translated
129
+ return translated , nil
106
130
}
107
131
}
108
132
133
+ return translated , err
134
+
135
+ }
136
+
137
+ translateAndLogIfNeeded := func (translationID string , templateData any ) string {
138
+ translated , err := translate (translationID , templateData )
139
+ if err == nil {
140
+ return translated
141
+ }
142
+
109
143
if _ , ok := err .(* i18n.MessageNotFoundErr ); ! ok {
110
- t .logger .Warnf ("Failed to get translated string for language %q and ID %q: %s" , currentLangStr , translationID , err )
144
+ ts .logger .Warnf ("Failed to get translated string for language %q and ID %q: %s" , currentLangStr , translationID , err )
111
145
}
112
146
113
- if t .cfg .GetBool ("logI18nWarnings" ) {
147
+ if ts .cfg .GetBool ("logI18nWarnings" ) {
114
148
i18nWarningLogger .Printf ("i18n|MISSING_TRANSLATION|%s|%s" , currentLangStr , translationID )
115
149
}
116
150
117
151
if enableMissingTranslationPlaceholders {
118
152
return "[i18n] " + translationID
119
153
}
120
-
121
154
return translated
122
155
}
156
+
157
+ ts .translators [currentLangKey ] = translator {
158
+ translate : translateAndLogIfNeeded ,
159
+ hasTranslation : func (translationID string ) bool {
160
+ _ , err := translate (translationID , nil )
161
+ return err == nil
162
+ },
163
+ }
123
164
}
124
165
}
125
166
0 commit comments