5 Commits

Author SHA1 Message Date
Leonel Quinteros
ad380b8ede Fix Locale.findPO to support language code simplification on LC_MESSAGES dir. 2016-07-01 11:21:13 -03:00
Leonel Quinteros
e62229fc8e Merge pull request #3 from cinghiale/support_LC_MESSAGES
added support for .po files stored in a LC_MESSAGES subdir
2016-07-01 10:59:45 -03:00
David Mugnai
8a0f825cf4 added support for .po files stored in a LC_MESSAGES subdir 2016-07-01 15:41:56 +02:00
Leonel Quinteros
f9c18b1237 Improved docs 2016-06-26 15:52:59 -03:00
Leonel Quinteros
80c24ef4e1 Link v1.0.0 release 2016-06-26 15:46:47 -03:00
4 changed files with 56 additions and 39 deletions

View File

@@ -4,21 +4,21 @@
GNU gettext utilities for Go.
Version: [0.9.1](https://github.com/leonelquinteros/gotext/releases/tag/v0.9.1)
Version: [1.0.1](https://github.com/leonelquinteros/gotext/releases/tag/v1.0.1)
#Features
# Features
- Implements GNU gettext support in native Go.
- Safe for concurrent use across multiple goroutines.
- It works with UTF-8 encoding as it's the default for Go language.
- Unit tests available.
- Language codes are automatically simplified from the form "en_UK" to "en" if the first isn't available.
- Ready to use inside Go templates.
- Complete support for [PO files](https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html).
- Support for [pluralization rules](https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html).
- Support for [message context](https://www.gnu.org/software/gettext/manual/html_node/Contexts.html).
- Support for variables inside translation strings using Go's [fmt package syntax](https://golang.org/pkg/fmt/).
- Thread-safe: This package is safe for concurrent use across multiple goroutines.
- It works with UTF-8 encoding as it's the default for Go language.
- Unit tests available.
- Language codes are automatically simplified from the form `en_UK` to `en` if the first isn't available.
- Ready to use inside Go templates.
# Installation
@@ -49,25 +49,29 @@ or to object constructors depending on the use, but either will use the same con
Inside the base directory where will be the language directories named using the language and country 2-letter codes (en_US, es_AR, ...).
All package functions can lookup after the simplified version for each language in case the full code isn't present but the more general language code exists.
So if the language set is "en_UK", but there is no directory named after that code and there is a directory named "en",
So if the language set is `en_UK`, but there is no directory named after that code and there is a directory named `en`,
all package functions will be able to resolve this generalization and provide translations for the more general library.
The language codes are assumed to be [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) codes (2-letter codes).
That said, most functions will work with any coding standard as long the directory name matches the language code set on the configuration.
A normal library directory structure may look like:
Then, there can be a `LC_MESSAGES` containing all PO files or the PO files themselves.
A library directory structure can look like:
```
/path/to/locales
/path/to/locales/en_US
/path/to/locales/en_US/default.po
/path/to/locales/en_US/extras.po
/path/to/locales/en_US/LC_MESSAGES
/path/to/locales/en_US/LC_MESSAGES/default.po
/path/to/locales/en_US/LC_MESSAGES/extras.po
/path/to/locales/en_UK
/path/to/locales/en_UK/default.po
/path/to/locales/en_UK/extras.po
/path/to/locales/en_UK/LC_MESSAGES
/path/to/locales/en_UK/LC_MESSAGES/default.po
/path/to/locales/en_UK/LC_MESSAGES/extras.po
/path/to/locales/en_AU
/path/to/locales/en_AU/default.po
/path/to/locales/en_AU/extras.po
/path/to/locales/en_AU/LC_MESSAGES
/path/to/locales/en_AU/LC_MESSAGES/default.po
/path/to/locales/en_AU/LC_MESSAGES/extras.po
/path/to/locales/es
/path/to/locales/es/default.po
/path/to/locales/es/extras.po
@@ -85,9 +89,9 @@ And so on...
# About translation function names
The standard GNU gettext defines helper functions that maps to the gettext() function and it's widely adopted by most implementations.
The standard GNU gettext defines helper functions that maps to the `gettext()` function and it's widely adopted by most implementations.
The basic translation function is usually _() in the form:
The basic translation function is usually `_()` in the form:
```
_("Translate this")
@@ -110,7 +114,7 @@ func _(str string, vars ...interface{}) string {
This is valid and can be used within a package.
In normal conditions the Go compiler will optimize the calls to _() by replacing its content in place of the function call to reduce the function calling overhead.
In normal conditions the Go compiler will optimize the calls to `_()` by replacing its content in place of the function call to reduce the function calling overhead.
This is a normal Go compiler behavior.

View File

@@ -1,8 +1,6 @@
/*
Package gotext implements GNU gettext utilities.
Version 0.9.0 (stable)
For quick/simple translations you can use the package level functions directly.
import "github.com/leonelquinteros/gotext"

View File

@@ -20,13 +20,13 @@ Example:
// Create Locale with library path and language code
l := gotext.NewLocale("/path/to/i18n/dir", "en_US")
// Load domain '/path/to/i18n/dir/en_US/default.po'
// Load domain '/path/to/i18n/dir/en_US/LC_MESSAGES/default.po'
l.AddDomain("default")
// Translate text from default domain
println(l.Get("Translate this"))
// Load different domain ('/path/to/i18n/dir/en_US/extras.po')
// Load different domain ('/path/to/i18n/dir/en_US/LC_MESSAGES/extras.po')
l.AddDomain("extras")
// Translate text from domain
@@ -58,23 +58,38 @@ func NewLocale(p, l string) *Locale {
}
}
func (l *Locale) findPO(dom string) string {
filename := path.Join(l.path, l.lang, "LC_MESSAGES", dom+".po")
if _, err := os.Stat(filename); err == nil {
return filename
}
if len(l.lang) > 2 {
filename = path.Join(l.path, l.lang[:2], "LC_MESSAGES", dom+".po")
if _, err := os.Stat(filename); err == nil {
return filename
}
}
filename = path.Join(l.path, l.lang, dom+".po")
if _, err := os.Stat(filename); err == nil {
return filename
}
if len(l.lang) > 2 {
filename = path.Join(l.path, l.lang[:2], dom+".po")
}
return filename
}
// AddDomain creates a new domain for a given locale object and initializes the Po object.
// If the domain exists, it gets reloaded.
func (l *Locale) AddDomain(dom string) {
po := new(Po)
// Check for file.
filename := path.Clean(l.path + string(os.PathSeparator) + l.lang + string(os.PathSeparator) + dom + ".po")
// Try to use the generic language dir if the provided isn't available
if _, err := os.Stat(filename); err != nil {
if len(l.lang) > 2 {
filename = path.Clean(l.path + string(os.PathSeparator) + l.lang[:2] + string(os.PathSeparator) + dom + ".po")
}
}
// Parse file.
po.ParseFile(filename)
po.ParseFile(l.findPO(dom))
// Save new domain
l.Lock()

View File

@@ -49,14 +49,14 @@ msgstr "More translation"
`
// Create Locales directory with simplified language code
dirname := path.Clean("/tmp" + string(os.PathSeparator) + "en")
dirname := path.Join("/tmp", "en", "LC_MESSAGES")
err := os.MkdirAll(dirname, os.ModePerm)
if err != nil {
t.Fatalf("Can't create test directory: %s", err.Error())
}
// Write PO content to file
filename := path.Clean(dirname + string(os.PathSeparator) + "my_domain.po")
filename := path.Join(dirname, "my_domain.po")
f, err := os.Create(filename)
if err != nil {
@@ -168,14 +168,14 @@ msgstr[2] "And this is the second plural form: %s"
`
// Create Locales directory with simplified language code
dirname := path.Clean("/tmp" + string(os.PathSeparator) + "es")
dirname := path.Join("/tmp", "es")
err := os.MkdirAll(dirname, os.ModePerm)
if err != nil {
t.Fatalf("Can't create test directory: %s", err.Error())
}
// Write PO content to file
filename := path.Clean(dirname + string(os.PathSeparator) + "race.po")
filename := path.Join(dirname, "race.po")
f, err := os.Create(filename)
if err != nil {