allow locale to work with a fs.FS
Signed-off-by: jkoberg <jkoberg@owncloud.com>
This commit is contained in:
parent
6f9bcaa969
commit
9d5a301452
4 changed files with 57 additions and 9 deletions
37
locale.go
37
locale.go
|
@ -8,6 +8,7 @@ package gotext
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
"sync"
|
||||
|
@ -60,6 +61,9 @@ type Locale struct {
|
|||
|
||||
// Sync Mutex
|
||||
sync.RWMutex
|
||||
|
||||
// optional fs to use
|
||||
fs fs.FS
|
||||
}
|
||||
|
||||
// NewLocale creates and initializes a new Locale object for a given language.
|
||||
|
@ -72,27 +76,34 @@ func NewLocale(p, l string) *Locale {
|
|||
}
|
||||
}
|
||||
|
||||
// NewLocaleFS returns a Locale working with a fs.FS
|
||||
func NewLocaleFS(p, l string, filesystem fs.FS) *Locale {
|
||||
loc := NewLocale(p, l)
|
||||
loc.fs = filesystem
|
||||
return loc
|
||||
}
|
||||
|
||||
func (l *Locale) findExt(dom, ext string) string {
|
||||
filename := path.Join(l.path, l.lang, "LC_MESSAGES", dom+"."+ext)
|
||||
if _, err := os.Stat(filename); err == nil {
|
||||
if l.fileExists(filename) {
|
||||
return filename
|
||||
}
|
||||
|
||||
if len(l.lang) > 2 {
|
||||
filename = path.Join(l.path, l.lang[:2], "LC_MESSAGES", dom+"."+ext)
|
||||
if _, err := os.Stat(filename); err == nil {
|
||||
if l.fileExists(filename) {
|
||||
return filename
|
||||
}
|
||||
}
|
||||
|
||||
filename = path.Join(l.path, l.lang, dom+"."+ext)
|
||||
if _, err := os.Stat(filename); err == nil {
|
||||
if l.fileExists(filename) {
|
||||
return filename
|
||||
}
|
||||
|
||||
if len(l.lang) > 2 {
|
||||
filename = path.Join(l.path, l.lang[:2], dom+"."+ext)
|
||||
if _, err := os.Stat(filename); err == nil {
|
||||
if l.fileExists(filename) {
|
||||
return filename
|
||||
}
|
||||
}
|
||||
|
@ -100,6 +111,20 @@ func (l *Locale) findExt(dom, ext string) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func (l *Locale) fileExists(filename string) bool {
|
||||
if l.fs != nil {
|
||||
f, err := l.fs.Open(filename)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
_, err = f.Stat()
|
||||
return err == nil
|
||||
|
||||
}
|
||||
_, err := os.Stat(filename)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// 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) {
|
||||
|
@ -107,13 +132,13 @@ func (l *Locale) AddDomain(dom string) {
|
|||
|
||||
file := l.findExt(dom, "po")
|
||||
if file != "" {
|
||||
poObj = NewPo()
|
||||
poObj = NewPoFS(l.fs)
|
||||
// Parse file.
|
||||
poObj.ParseFile(file)
|
||||
} else {
|
||||
file = l.findExt(dom, "mo")
|
||||
if file != "" {
|
||||
poObj = NewMo()
|
||||
poObj = NewMoFS(l.fs)
|
||||
// Parse file.
|
||||
poObj.ParseFile(file)
|
||||
} else {
|
||||
|
|
11
mo.go
11
mo.go
|
@ -8,6 +8,7 @@ package gotext
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"io/fs"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -52,6 +53,7 @@ type Mo struct {
|
|||
Language string
|
||||
PluralForms string
|
||||
domain *Domain
|
||||
fs fs.FS
|
||||
}
|
||||
|
||||
//NewMo should always be used to instantiate a new Mo object
|
||||
|
@ -62,6 +64,13 @@ func NewMo() *Mo {
|
|||
return mo
|
||||
}
|
||||
|
||||
// NewMoFS works like NewMO but adds an optional fs.FS
|
||||
func NewMoFS(filesystem fs.FS) *Mo {
|
||||
mo := NewMo()
|
||||
mo.fs = filesystem
|
||||
return mo
|
||||
}
|
||||
|
||||
func (mo *Mo) GetDomain() *Domain {
|
||||
return mo.domain
|
||||
}
|
||||
|
@ -92,7 +101,7 @@ func (mo *Mo) UnmarshalBinary(data []byte) error {
|
|||
}
|
||||
|
||||
func (mo *Mo) ParseFile(f string) {
|
||||
data, err := getFileData(f)
|
||||
data, err := getFileData(f, mo.fs)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
11
po.go
11
po.go
|
@ -6,6 +6,7 @@
|
|||
package gotext
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
@ -41,6 +42,7 @@ type Po struct {
|
|||
PluralForms string
|
||||
|
||||
domain *Domain
|
||||
fs fs.FS
|
||||
}
|
||||
|
||||
type parseState int
|
||||
|
@ -61,6 +63,13 @@ func NewPo() *Po {
|
|||
return po
|
||||
}
|
||||
|
||||
// NewPoFS works like NewPO but adds an optional fs.FS
|
||||
func NewPoFS(filesystem fs.FS) *Po {
|
||||
po := NewPo()
|
||||
po.fs = filesystem
|
||||
return po
|
||||
}
|
||||
|
||||
func (po *Po) GetDomain() *Domain {
|
||||
return po.domain
|
||||
}
|
||||
|
@ -118,7 +127,7 @@ func (po *Po) UnmarshalBinary(data []byte) error {
|
|||
}
|
||||
|
||||
func (po *Po) ParseFile(f string) {
|
||||
data, err := getFileData(f)
|
||||
data, err := getFileData(f, po.fs)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ package gotext
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
@ -66,7 +67,11 @@ func (te *TranslatorEncoding) GetTranslator() Translator {
|
|||
}
|
||||
|
||||
//getFileData reads a file and returns the byte slice after doing some basic sanity checking
|
||||
func getFileData(f string) ([]byte, error) {
|
||||
func getFileData(f string, filesystem fs.FS) ([]byte, error) {
|
||||
if filesystem != nil {
|
||||
return fs.ReadFile(filesystem, f)
|
||||
}
|
||||
|
||||
// Check if file exists
|
||||
info, err := os.Stat(f)
|
||||
if err != nil {
|
||||
|
|
Loading…
Reference in a new issue