This repository has been archived by the owner on Jan 11, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 558
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
First round of i18n in acs-engine based on gettext. Subsequent change…
…s will replace and extract resource strings in acs-engine and make acsengine/api package's i18n used by other go program.
- Loading branch information
1 parent
8b365e0
commit ecdd9b9
Showing
13 changed files
with
342 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
package i18n | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"os" | ||
"strings" | ||
|
||
"github.com/leonelquinteros/gotext" | ||
) | ||
|
||
const ( | ||
defaultLanguage = "default" | ||
defaultDomain = "acsengine" | ||
defaultLocalDir = "translations" | ||
) | ||
|
||
var supportedTranslations = map[string]bool{ | ||
defaultLanguage: true, | ||
"en_US": true, | ||
"zh_CN": true, | ||
} | ||
|
||
func loadSystemLanguage() string { | ||
language := os.Getenv("LANG") | ||
if language == "" { | ||
return defaultLanguage | ||
} | ||
|
||
// Posix locale name usually has the ll_CC.encoding syntax. | ||
parts := strings.Split(language, ".") | ||
if len(parts) == 0 { | ||
return defaultLanguage | ||
} | ||
return parts[0] | ||
} | ||
|
||
// LoadTranslations loads translation files and sets the locale to | ||
// the system locale. It should be called by the main program. | ||
func LoadTranslations(translationsDir string) (*gotext.Locale, error) { | ||
dir := defaultLocalDir | ||
if translationsDir != "" { | ||
dir = translationsDir | ||
} | ||
|
||
if stat, err := os.Stat(dir); os.IsNotExist(err) || !stat.IsDir() { | ||
return nil, fmt.Errorf("Translations directory %s does not exist: %v", dir, err) | ||
} | ||
|
||
lang := loadSystemLanguage() | ||
SetLanguage(lang) | ||
|
||
locale := gotext.NewLocale(dir, lang) | ||
Initialize(locale) | ||
|
||
return locale, nil | ||
} | ||
|
||
// Initialize is the translation initialization function shared by the main program and package. | ||
func Initialize(locale *gotext.Locale) error { | ||
if locale == nil { | ||
return fmt.Errorf("Initialize expected locale but got nil") | ||
} | ||
locale.AddDomain(defaultDomain) | ||
return nil | ||
} | ||
|
||
// SetLanguage sets the program's current locale. If the language is not | ||
// supported, then the default locale is used. | ||
func SetLanguage(language string) { | ||
if _, ok := supportedTranslations[language]; ok { | ||
gotext.SetLanguage(language) | ||
return | ||
} | ||
gotext.SetLanguage(defaultLanguage) | ||
} | ||
|
||
// GetLanguage queries the program's current locale. | ||
func GetLanguage() string { | ||
return gotext.GetLanguage() | ||
} | ||
|
||
// Translator is a wrapper over gotext's Locale and provides interface to | ||
// translate text string and produce translated error | ||
type Translator struct { | ||
Locale *gotext.Locale | ||
} | ||
|
||
// T translates a text string, based on GNU's gettext library. | ||
func (t *Translator) T(msgid string, vars ...interface{}) string { | ||
return t.Locale.GetD(defaultDomain, msgid, vars...) | ||
} | ||
|
||
// NT translates a text string into the appropriate plural form, based on GNU's gettext library. | ||
func (t *Translator) NT(msgid, msgidPlural string, n int, vars ...interface{}) string { | ||
return t.Locale.GetND(defaultDomain, msgid, msgidPlural, n, vars...) | ||
} | ||
|
||
// Errorf produces an error with a translated error string. | ||
func (t *Translator) Errorf(msgid string, vars ...interface{}) error { | ||
return errors.New(t.T(msgid, vars...)) | ||
} | ||
|
||
// NErrorf produces an error with a translated error string in the appropriate plural form. | ||
func (t *Translator) NErrorf(msgid, msgidPlural string, n int, vars ...interface{}) error { | ||
return errors.New(t.NT(msgid, msgidPlural, n, vars...)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package i18n | ||
|
||
import ( | ||
"os" | ||
"path" | ||
"testing" | ||
|
||
. "github.com/onsi/gomega" | ||
) | ||
|
||
func TestLoadTranslations(t *testing.T) { | ||
RegisterTestingT(t) | ||
|
||
_, err := LoadTranslations(path.Join("..", "..", "translations", "test")) | ||
Expect(err).Should(BeNil()) | ||
|
||
_, err = LoadTranslations("non_existing_directory") | ||
Expect(err).ShouldNot(BeNil()) | ||
} | ||
|
||
func TestTranslationLanguage(t *testing.T) { | ||
RegisterTestingT(t) | ||
|
||
origLang := os.Getenv("LANG") | ||
os.Setenv("LANG", "en_US.UTF-8") | ||
_, err := LoadTranslations(path.Join("..", "..", "translations", "test")) | ||
Expect(err).Should(BeNil()) | ||
|
||
lang := GetLanguage() | ||
Expect(lang).Should(Equal("en_US")) | ||
|
||
os.Setenv("LANG", origLang) | ||
} | ||
|
||
func TestTranslationLanguageDefault(t *testing.T) { | ||
RegisterTestingT(t) | ||
|
||
origLang := os.Getenv("LANG") | ||
os.Setenv("LANG", "ll_CC.UTF-8") | ||
_, err := LoadTranslations(path.Join("..", "..", "translations", "test")) | ||
Expect(err).Should(BeNil()) | ||
|
||
lang := GetLanguage() | ||
Expect(lang).Should(Equal("default")) | ||
|
||
os.Setenv("LANG", origLang) | ||
} | ||
|
||
func TestTranslations(t *testing.T) { | ||
RegisterTestingT(t) | ||
|
||
l, err := LoadTranslations(path.Join("..", "..", "translations", "test")) | ||
Expect(err).Should(BeNil()) | ||
|
||
translator := &Translator{ | ||
Locale: l, | ||
} | ||
|
||
msg := translator.T("Aloha") | ||
Expect(msg).Should(Equal("Aloha")) | ||
|
||
msg = translator.T("Hello %s", "World") | ||
Expect(msg).Should(Equal("Hello World")) | ||
} | ||
|
||
func TestTranslationsPlural(t *testing.T) { | ||
RegisterTestingT(t) | ||
|
||
l, err := LoadTranslations(path.Join("..", "..", "translations", "test")) | ||
Expect(err).Should(BeNil()) | ||
|
||
translator := &Translator{ | ||
Locale: l, | ||
} | ||
|
||
msg := translator.NT("There is %d parameter in resource %s", "There are %d parameters in resource %s", 1, 1, "Foo") | ||
Expect(msg).Should(Equal("There is 1 parameter in resource Foo")) | ||
|
||
msg = translator.NT("There is %d parameter in resource %s", "There are %d parameters in resource %s", 9, 9, "Foo") | ||
Expect(msg).Should(Equal("There are 9 parameters in resource Foo")) | ||
} |
Oops, something went wrong.