2017-02-04 22:20:06 -05:00
// Copyright 2017 The Hugo Authors. All rights reserved.
2016-05-14 00:35:16 -04:00
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
2017-02-04 22:20:06 -05:00
package i18n
2016-05-14 00:35:16 -04:00
import (
2018-10-03 08:58:09 -04:00
"github.com/gohugoio/hugo/common/loggers"
2017-06-13 12:42:45 -04:00
"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/helpers"
2018-10-03 08:58:09 -04:00
2017-06-13 13:07:35 -04:00
"github.com/nicksnyder/go-i18n/i18n/bundle"
2019-04-23 13:24:19 -04:00
"github.com/nicksnyder/go-i18n/i18n/translation"
2016-08-09 05:41:56 -04:00
)
var (
i18nWarningLogger = helpers . NewDistinctFeedbackLogger ( )
2016-05-14 00:35:16 -04:00
)
2017-02-04 22:20:06 -05:00
// Translator handles i18n translations.
type Translator struct {
2016-07-26 08:44:37 -04:00
translateFuncs map [ string ] bundle . TranslateFunc
2017-02-04 22:20:06 -05:00
cfg config . Provider
2018-10-03 08:58:09 -04:00
logger * loggers . Logger
2016-07-26 08:44:37 -04:00
}
2017-02-04 22:20:06 -05:00
// NewTranslator creates a new Translator for the given language bundle and configuration.
2018-10-03 08:58:09 -04:00
func NewTranslator ( b * bundle . Bundle , cfg config . Provider , logger * loggers . Logger ) Translator {
2017-02-04 22:20:06 -05:00
t := Translator { cfg : cfg , logger : logger , translateFuncs : make ( map [ string ] bundle . TranslateFunc ) }
t . initFuncs ( b )
return t
}
2016-07-26 08:44:37 -04:00
2017-02-04 22:20:06 -05:00
// Func gets the translate func for the given language, or for the default
// configured language if not found.
func ( t Translator ) Func ( lang string ) bundle . TranslateFunc {
if f , ok := t . translateFuncs [ lang ] ; ok {
return f
}
Make WARN the new default log log level
This commit also pulls down the log level for a set of WARN statements to INFO. There should be no ERRORs or WARNINGs in a regular Hugo build. That is the story about the Boy Who Cried Wolf.
Since the WARN log is now more visible, this commit also improves on some of them, most notable the "layout not found", which now would look something like this:
```bash
WARN 2018/11/02 09:02:18 Found no layout for "home", language "en", output format "CSS": create a template below /layouts with one of these filenames: index.en.css.css, home.en.css.css, list.en.css.css, index.css.css, home.css.css, list.css.css, index.en.css, home.en.css, list.en.css, index.css, home.css, list.css, _default/index.en.css.css, _default/home.en.css.css, _default/list.en.css.css, _default/index.css.css, _default/home.css.css, _default/list.css.css, _default/index.en.css, _default/home.en.css, _default/list.en.css, _default/index.css, _default/home.css, _default/list.css
```
Fixes #5203
2018-11-01 17:27:42 -04:00
t . logger . INFO . Printf ( "Translation func for language %v not found, use default." , lang )
2017-02-04 22:20:06 -05:00
if f , ok := t . translateFuncs [ t . cfg . GetString ( "defaultContentLanguage" ) ] ; ok {
return f
}
Make WARN the new default log log level
This commit also pulls down the log level for a set of WARN statements to INFO. There should be no ERRORs or WARNINGs in a regular Hugo build. That is the story about the Boy Who Cried Wolf.
Since the WARN log is now more visible, this commit also improves on some of them, most notable the "layout not found", which now would look something like this:
```bash
WARN 2018/11/02 09:02:18 Found no layout for "home", language "en", output format "CSS": create a template below /layouts with one of these filenames: index.en.css.css, home.en.css.css, list.en.css.css, index.css.css, home.css.css, list.css.css, index.en.css, home.en.css, list.en.css, index.css, home.css, list.css, _default/index.en.css.css, _default/home.en.css.css, _default/list.en.css.css, _default/index.css.css, _default/home.css.css, _default/list.css.css, _default/index.en.css, _default/home.en.css, _default/list.en.css, _default/index.css, _default/home.css, _default/list.css
```
Fixes #5203
2018-11-01 17:27:42 -04:00
t . logger . INFO . Println ( "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." )
2017-02-04 22:20:06 -05:00
return func ( translationID string , args ... interface { } ) string {
return ""
2016-07-26 08:44:37 -04:00
}
2017-02-04 22:20:06 -05:00
2016-07-26 08:44:37 -04:00
}
2017-02-04 22:20:06 -05:00
func ( t Translator ) initFuncs ( bndl * bundle . Bundle ) {
defaultContentLanguage := t . cfg . GetString ( "defaultContentLanguage" )
2016-08-09 05:41:56 -04:00
2017-05-03 03:11:14 -04:00
defaultT , err := bndl . Tfunc ( defaultContentLanguage )
2016-08-09 05:41:56 -04:00
if err != nil {
Make WARN the new default log log level
This commit also pulls down the log level for a set of WARN statements to INFO. There should be no ERRORs or WARNINGs in a regular Hugo build. That is the story about the Boy Who Cried Wolf.
Since the WARN log is now more visible, this commit also improves on some of them, most notable the "layout not found", which now would look something like this:
```bash
WARN 2018/11/02 09:02:18 Found no layout for "home", language "en", output format "CSS": create a template below /layouts with one of these filenames: index.en.css.css, home.en.css.css, list.en.css.css, index.css.css, home.css.css, list.css.css, index.en.css, home.en.css, list.en.css, index.css, home.css, list.css, _default/index.en.css.css, _default/home.en.css.css, _default/list.en.css.css, _default/index.css.css, _default/home.css.css, _default/list.css.css, _default/index.en.css, _default/home.en.css, _default/list.en.css, _default/index.css, _default/home.css, _default/list.css
```
Fixes #5203
2018-11-01 17:27:42 -04:00
t . logger . INFO . Printf ( "No translation bundle found for default language %q" , defaultContentLanguage )
2016-08-09 05:41:56 -04:00
}
2019-04-23 13:24:19 -04:00
translations := bndl . Translations ( )
2017-02-04 22:20:06 -05:00
enableMissingTranslationPlaceholders := t . cfg . GetBool ( "enableMissingTranslationPlaceholders" )
2016-07-26 08:44:37 -04:00
for _ , lang := range bndl . LanguageTags ( ) {
2016-08-09 05:41:56 -04:00
currentLang := lang
2017-02-04 22:20:06 -05:00
t . translateFuncs [ currentLang ] = func ( translationID string , args ... interface { } ) string {
2016-09-18 16:18:13 -04:00
tFunc , err := bndl . Tfunc ( currentLang )
if err != nil {
2018-10-28 09:42:41 -04:00
t . logger . WARN . Printf ( "could not load translations for language %q (%s), will use default content language.\n" , lang , err )
2017-05-02 13:01:05 -04:00
}
translated := tFunc ( translationID , args ... )
2017-05-03 03:11:14 -04:00
if translated != translationID {
return translated
}
2017-05-02 13:01:05 -04:00
// If there is no translation for translationID,
// then Tfunc returns translationID itself.
2017-05-03 03:11:14 -04:00
// But if user set same translationID and translation, we should check
// if it really untranslated:
2019-04-23 13:24:19 -04:00
if isIDTranslated ( translations , currentLang , translationID ) {
2016-08-09 05:41:56 -04:00
return translated
}
2017-05-03 03:11:14 -04:00
2017-02-04 22:20:06 -05:00
if t . cfg . GetBool ( "logI18nWarnings" ) {
2016-08-09 05:41:56 -04:00
i18nWarningLogger . Printf ( "i18n|MISSING_TRANSLATION|%s|%s" , currentLang , translationID )
}
2016-11-06 18:10:32 -05:00
if enableMissingTranslationPlaceholders {
2016-11-18 16:38:41 -05:00
return "[i18n] " + translationID
2016-09-18 16:18:13 -04:00
}
2016-08-09 05:41:56 -04:00
if defaultT != nil {
2017-05-03 03:11:14 -04:00
translated := defaultT ( translationID , args ... )
if translated != translationID {
return translated
}
2019-04-23 13:24:19 -04:00
if isIDTranslated ( translations , defaultContentLanguage , translationID ) {
2016-09-09 15:21:16 -04:00
return translated
}
2016-08-09 05:41:56 -04:00
}
2016-09-18 16:18:13 -04:00
return ""
2016-08-09 05:41:56 -04:00
}
2016-05-14 00:35:16 -04:00
}
}
2017-05-03 03:11:14 -04:00
2019-04-23 13:24:19 -04:00
// If the translation map contains translationID for specified currentLang,
2017-05-03 03:11:14 -04:00
// then the translationID is actually translated.
2019-04-23 13:24:19 -04:00
func isIDTranslated ( translations map [ string ] map [ string ] translation . Translation , lang , id string ) bool {
_ , contains := translations [ lang ] [ id ]
2017-05-03 03:11:14 -04:00
return contains
}