mirror of
				https://github.com/gohugoio/hugo.git
				synced 2024-05-11 05:54:58 +00:00 
			
		
		
		
	tpl: Improve tests and docs for i18n
This commit is contained in:
		
				
					committed by
					
						
						Bjørn Erik Pedersen
					
				
			
			
				
	
			
			
			
						parent
						
							e7ff5c2d6a
						
					
				
				
					commit
					e7e2a1ca02
				
			@@ -190,17 +190,16 @@ The rendering of the main navigation works as usual. `.Site.Menus` will just con
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
An empty string will be shown if the translation for the current language is missing and no default value is set.
 | 
			
		||||
### Missing translations
 | 
			
		||||
 | 
			
		||||
While translating a Hugo website it can be handy to have a visual indicator as well. The `EnableMissingTranslationPlaceholders` config option allows you to replace the empty string with a placeholder like `[i18n] identifier`, where `identifier` is the id of the missing translation.
 | 
			
		||||
If a string does not have a translation for the current language, Hugo will use the value from the default language. If no default value is set, an empty string will be shown.
 | 
			
		||||
 | 
			
		||||
While translating a Hugo site, it can be handy to have a visual indicator of missing translations. The `EnableMissingTranslationPlaceholders` config option will flag all untranslated strings with the placeholder `[i18n] identifier`, where `identifier` is the id of the missing translation.
 | 
			
		||||
 | 
			
		||||
**Remember: Hugo will generate your website with these placeholders. It might not be suited for production environments.**
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Multilingual Themes support
 | 
			
		||||
 | 
			
		||||
To support Multilingual mode in your themes, some considerations must be taken for the URLs in the templates. If there are more than one language, URLs  must either  come from the built-in `.Permalink` or `.URL`, be constructed with `relLangURL` or `absLangURL` template funcs -- or prefixed with `{{.LanguagePrefix }}`.
 | 
			
		||||
 | 
			
		||||
If there are more than one language defined, the`LanguagePrefix` variable will equal `"/en"` (or whatever your `CurrentLanguage` is). If not enabled, it will be an empty string, so it is harmless for single-language sites.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -135,7 +135,7 @@ along with their current, default values:
 | 
			
		||||
    # Enable Emoji emoticons support for page content.
 | 
			
		||||
    # See www.emoji-cheat-sheet.com
 | 
			
		||||
    enableEmoji:				false
 | 
			
		||||
    # Show a placeholder like "[i18n] foo" instead of an empty string if a translation is missing
 | 
			
		||||
    # Show a placeholder instead of the default value or an empty string if a translation is missing
 | 
			
		||||
    enableMissingTranslationPlaceholders: false
 | 
			
		||||
    footnoteAnchorPrefix:       ""
 | 
			
		||||
    footnoteReturnLinkContents: ""
 | 
			
		||||
 
 | 
			
		||||
@@ -22,15 +22,94 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type test struct {
 | 
			
		||||
	file    string
 | 
			
		||||
	content []byte
 | 
			
		||||
	data                              map[string][]byte
 | 
			
		||||
	args                              interface{}
 | 
			
		||||
	lang, id, expected, expected_flag string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func doTestI18nTranslate(t *testing.T, data []test, lang, id string) string {
 | 
			
		||||
var tests []test = []test{
 | 
			
		||||
	// All translations present
 | 
			
		||||
	{
 | 
			
		||||
		data: map[string][]byte{
 | 
			
		||||
			"en.yaml": []byte("- id: \"hello\"\n  translation: \"Hello, World!\""),
 | 
			
		||||
			"es.yaml": []byte("- id: \"hello\"\n  translation: \"¡Hola, Mundo!\""),
 | 
			
		||||
		},
 | 
			
		||||
		args:          nil,
 | 
			
		||||
		lang:          "es",
 | 
			
		||||
		id:            "hello",
 | 
			
		||||
		expected:      "¡Hola, Mundo!",
 | 
			
		||||
		expected_flag: "¡Hola, Mundo!",
 | 
			
		||||
	},
 | 
			
		||||
	// Translation missing in current language but present in default
 | 
			
		||||
	{
 | 
			
		||||
		data: map[string][]byte{
 | 
			
		||||
			"en.yaml": []byte("- id: \"hello\"\n  translation: \"Hello, World!\""),
 | 
			
		||||
			"es.yaml": []byte("- id: \"goodbye\"\n  translation: \"¡Adiós, Mundo!\""),
 | 
			
		||||
		},
 | 
			
		||||
		args:          nil,
 | 
			
		||||
		lang:          "es",
 | 
			
		||||
		id:            "hello",
 | 
			
		||||
		expected:      "Hello, World!",
 | 
			
		||||
		expected_flag: "[i18n] hello",
 | 
			
		||||
	},
 | 
			
		||||
	// Translation missing in default language but present in current
 | 
			
		||||
	{
 | 
			
		||||
		data: map[string][]byte{
 | 
			
		||||
			"en.yaml": []byte("- id: \"goodybe\"\n  translation: \"Goodbye, World!\""),
 | 
			
		||||
			"es.yaml": []byte("- id: \"hello\"\n  translation: \"¡Hola, Mundo!\""),
 | 
			
		||||
		},
 | 
			
		||||
		args:          nil,
 | 
			
		||||
		lang:          "es",
 | 
			
		||||
		id:            "hello",
 | 
			
		||||
		expected:      "¡Hola, Mundo!",
 | 
			
		||||
		expected_flag: "¡Hola, Mundo!",
 | 
			
		||||
	},
 | 
			
		||||
	// Translation missing in both default and current language
 | 
			
		||||
	{
 | 
			
		||||
		data: map[string][]byte{
 | 
			
		||||
			"en.yaml": []byte("- id: \"goodbye\"\n  translation: \"Goodbye, World!\""),
 | 
			
		||||
			"es.yaml": []byte("- id: \"goodbye\"\n  translation: \"¡Adiós, Mundo!\""),
 | 
			
		||||
		},
 | 
			
		||||
		args:          nil,
 | 
			
		||||
		lang:          "es",
 | 
			
		||||
		id:            "hello",
 | 
			
		||||
		expected:      "",
 | 
			
		||||
		expected_flag: "[i18n] hello",
 | 
			
		||||
	},
 | 
			
		||||
	// Default translation file missing or empty
 | 
			
		||||
	{
 | 
			
		||||
		data: map[string][]byte{
 | 
			
		||||
			"en.yaml": []byte(""),
 | 
			
		||||
		},
 | 
			
		||||
		args:          nil,
 | 
			
		||||
		lang:          "es",
 | 
			
		||||
		id:            "hello",
 | 
			
		||||
		expected:      "",
 | 
			
		||||
		expected_flag: "[i18n] hello",
 | 
			
		||||
	},
 | 
			
		||||
	// Context provided
 | 
			
		||||
	{
 | 
			
		||||
		data: map[string][]byte{
 | 
			
		||||
			"en.yaml": []byte("- id: \"wordCount\"\n  translation: \"Hello, {{.WordCount}} people!\""),
 | 
			
		||||
			"es.yaml": []byte("- id: \"wordCount\"\n  translation: \"¡Hola, {{.WordCount}} gente!\""),
 | 
			
		||||
		},
 | 
			
		||||
		args: struct {
 | 
			
		||||
			WordCount int
 | 
			
		||||
		}{
 | 
			
		||||
			50,
 | 
			
		||||
		},
 | 
			
		||||
		lang:          "es",
 | 
			
		||||
		id:            "wordCount",
 | 
			
		||||
		expected:      "¡Hola, 50 gente!",
 | 
			
		||||
		expected_flag: "¡Hola, 50 gente!",
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func doTestI18nTranslate(t *testing.T, data map[string][]byte, lang, id string, args interface{}) string {
 | 
			
		||||
	i18nBundle := bundle.New()
 | 
			
		||||
 | 
			
		||||
	for _, r := range data {
 | 
			
		||||
		err := i18nBundle.ParseTranslationFileBytes(r.file, r.content)
 | 
			
		||||
	for file, content := range data {
 | 
			
		||||
		err := i18nBundle.ParseTranslationFileBytes(file, content)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("Error parsing translation file: %s", err)
 | 
			
		||||
		}
 | 
			
		||||
@@ -39,7 +118,7 @@ func doTestI18nTranslate(t *testing.T, data []test, lang, id string) string {
 | 
			
		||||
	SetI18nTfuncs(i18nBundle)
 | 
			
		||||
	SetTranslateLang(lang)
 | 
			
		||||
 | 
			
		||||
	translated, err := I18nTranslate(id, nil)
 | 
			
		||||
	translated, err := I18nTranslate(id, args)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Errorf("Error translating '%s': %s", id, err)
 | 
			
		||||
	}
 | 
			
		||||
@@ -47,7 +126,6 @@ func doTestI18nTranslate(t *testing.T, data []test, lang, id string) string {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestI18nTranslate(t *testing.T) {
 | 
			
		||||
	var data []test
 | 
			
		||||
	var actual, expected string
 | 
			
		||||
 | 
			
		||||
	viper.SetDefault("DefaultContentLanguage", "en")
 | 
			
		||||
@@ -56,60 +134,14 @@ func TestI18nTranslate(t *testing.T) {
 | 
			
		||||
	for _, enablePlaceholders := range []bool{false, true} {
 | 
			
		||||
		viper.Set("EnableMissingTranslationPlaceholders", enablePlaceholders)
 | 
			
		||||
 | 
			
		||||
		// All translations present
 | 
			
		||||
		data = []test{
 | 
			
		||||
			{"en.yaml", []byte("- id: \"hello\"\n  translation: \"Hello, World!\"")},
 | 
			
		||||
			{"es.yaml", []byte("- id: \"hello\"\n  translation: \"¡Hola, Mundo!\"")},
 | 
			
		||||
		for _, test := range tests {
 | 
			
		||||
			if enablePlaceholders {
 | 
			
		||||
				expected = test.expected_flag
 | 
			
		||||
			} else {
 | 
			
		||||
				expected = test.expected
 | 
			
		||||
			}
 | 
			
		||||
			actual = doTestI18nTranslate(t, test.data, test.lang, test.id, test.args)
 | 
			
		||||
			assert.Equal(t, expected, actual)
 | 
			
		||||
		}
 | 
			
		||||
		expected = "¡Hola, Mundo!"
 | 
			
		||||
		actual = doTestI18nTranslate(t, data, "es", "hello")
 | 
			
		||||
		assert.Equal(t, expected, actual)
 | 
			
		||||
 | 
			
		||||
		// Translation missing in current language but present in default
 | 
			
		||||
		data = []test{
 | 
			
		||||
			{"en.yaml", []byte("- id: \"hello\"\n  translation: \"Hello, World!\"")},
 | 
			
		||||
			{"es.yaml", []byte("- id: \"goodbye\"\n  translation: \"¡Adiós, Mundo!\"")},
 | 
			
		||||
		}
 | 
			
		||||
		if enablePlaceholders {
 | 
			
		||||
			expected = "[i18n] hello"
 | 
			
		||||
		} else {
 | 
			
		||||
			expected = "Hello, World!"
 | 
			
		||||
		}
 | 
			
		||||
		actual = doTestI18nTranslate(t, data, "es", "hello")
 | 
			
		||||
		assert.Equal(t, expected, actual)
 | 
			
		||||
 | 
			
		||||
		// Translation missing in default language but present in current
 | 
			
		||||
		data = []test{
 | 
			
		||||
			{"en.yaml", []byte("- id: \"goodbye\"\n  translation: \"Goodbye, World!\"")},
 | 
			
		||||
			{"es.yaml", []byte("- id: \"hello\"\n  translation: \"¡Hola, Mundo!\"")},
 | 
			
		||||
		}
 | 
			
		||||
		expected = "¡Hola, Mundo!"
 | 
			
		||||
		actual = doTestI18nTranslate(t, data, "es", "hello")
 | 
			
		||||
		assert.Equal(t, expected, actual)
 | 
			
		||||
 | 
			
		||||
		// Translation missing in both default and current language
 | 
			
		||||
		data = []test{
 | 
			
		||||
			{"en.yaml", []byte("- id: \"goodbye\"\n  translation: \"Goodbye, World!\"")},
 | 
			
		||||
			{"es.yaml", []byte("- id: \"goodbye\"\n  translation: \"¡Adiós, Mundo!\"")},
 | 
			
		||||
		}
 | 
			
		||||
		if enablePlaceholders {
 | 
			
		||||
			expected = "[i18n] hello"
 | 
			
		||||
		} else {
 | 
			
		||||
			expected = ""
 | 
			
		||||
		}
 | 
			
		||||
		actual = doTestI18nTranslate(t, data, "es", "hello")
 | 
			
		||||
		assert.Equal(t, expected, actual)
 | 
			
		||||
 | 
			
		||||
		// Default translation file missing or empty
 | 
			
		||||
		data = []test{
 | 
			
		||||
			{"en.yaml", []byte("")},
 | 
			
		||||
		}
 | 
			
		||||
		actual = doTestI18nTranslate(t, data, "es", "hello")
 | 
			
		||||
		if enablePlaceholders {
 | 
			
		||||
			expected = "[i18n] hello"
 | 
			
		||||
		} else {
 | 
			
		||||
			expected = ""
 | 
			
		||||
		}
 | 
			
		||||
		assert.Equal(t, expected, actual)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user