Add support for multi-line msgid
This commit is contained in:
@@ -32,8 +32,8 @@ func TestGettersSetters(t *testing.T) {
|
||||
func TestPackageFunctions(t *testing.T) {
|
||||
// Set PO content
|
||||
str := `
|
||||
msgid ""
|
||||
msgstr ""
|
||||
# msgid ""
|
||||
# msgstr ""
|
||||
# Initial comment
|
||||
# Headers below
|
||||
"Language: en\n"
|
||||
@@ -79,7 +79,7 @@ msgstr "Some random translation in a context"
|
||||
msgid "More"
|
||||
msgstr "More translation"
|
||||
|
||||
`
|
||||
`
|
||||
|
||||
// Create Locales directory on default location
|
||||
dirname := path.Clean("/tmp" + string(os.PathSeparator) + "en_US")
|
||||
@@ -157,7 +157,7 @@ msgstr[0] "This one is the singular: %s"
|
||||
msgstr[1] "This one is the plural: %s"
|
||||
msgstr[2] "And this is the second plural form: %s"
|
||||
|
||||
`
|
||||
`
|
||||
|
||||
// Create Locales directory on default location
|
||||
dirname := path.Clean(library + string(os.PathSeparator) + "en_US")
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
func TestLocale(t *testing.T) {
|
||||
// Set PO content
|
||||
str := `
|
||||
msgid ""
|
||||
msgstr ""
|
||||
# msgid ""
|
||||
# msgstr ""
|
||||
# Initial comment
|
||||
# Headers below
|
||||
"Language: en\n"
|
||||
@@ -56,7 +56,7 @@ msgstr "Some random translation in a context"
|
||||
msgid "More"
|
||||
msgstr "More translation"
|
||||
|
||||
`
|
||||
`
|
||||
|
||||
// Create Locales directory with simplified language code
|
||||
dirname := path.Join("/tmp", "en", "LC_MESSAGES")
|
||||
@@ -176,7 +176,7 @@ msgstr "Some random translation in a context"
|
||||
msgid "More"
|
||||
msgstr "More translation"
|
||||
|
||||
`
|
||||
`
|
||||
|
||||
// Create Locales directory with simplified language code
|
||||
dirname := path.Join("/tmp", "en", "LC_MESSAGES")
|
||||
@@ -259,7 +259,7 @@ msgstr[0] "This one is the singular: %s"
|
||||
msgstr[1] "This one is the plural: %s"
|
||||
msgstr[2] "And this is the second plural form: %s"
|
||||
|
||||
`
|
||||
`
|
||||
|
||||
// Create Locales directory with simplified language code
|
||||
dirname := path.Join("/tmp", "es")
|
||||
|
||||
76
po.go
76
po.go
@@ -52,18 +52,18 @@ And it's safe for concurrent use by multiple goroutines by using the sync packag
|
||||
|
||||
Example:
|
||||
|
||||
import "github.com/leonelquinteros/gotext"
|
||||
import "github.com/leonelquinteros/gotext"
|
||||
|
||||
func main() {
|
||||
// Create po object
|
||||
po := new(gotext.Po)
|
||||
func main() {
|
||||
// Create po object
|
||||
po := new(gotext.Po)
|
||||
|
||||
// Parse .po file
|
||||
po.ParseFile("/path/to/po/file/translations.po")
|
||||
// Parse .po file
|
||||
po.ParseFile("/path/to/po/file/translations.po")
|
||||
|
||||
// Get translation
|
||||
println(po.Get("Translate this"))
|
||||
}
|
||||
// Get translation
|
||||
println(po.Get("Translate this"))
|
||||
}
|
||||
|
||||
*/
|
||||
type Po struct {
|
||||
@@ -92,6 +92,16 @@ type Po struct {
|
||||
ctxBuffer string
|
||||
}
|
||||
|
||||
type parseState int
|
||||
|
||||
const (
|
||||
head parseState = iota
|
||||
msgCtxt
|
||||
msgID
|
||||
msgIDPlural
|
||||
msgStr
|
||||
)
|
||||
|
||||
// ParseFile tries to read the file by its provided path (f) and parse its content as a .po file.
|
||||
func (po *Po) ParseFile(f string) {
|
||||
// Check if file exists
|
||||
@@ -133,6 +143,7 @@ func (po *Po) Parse(str string) {
|
||||
po.trBuffer = newTranslation()
|
||||
po.ctxBuffer = ""
|
||||
|
||||
state := head
|
||||
for _, l := range lines {
|
||||
// Trim spaces
|
||||
l = strings.TrimSpace(l)
|
||||
@@ -145,30 +156,34 @@ func (po *Po) Parse(str string) {
|
||||
// Buffer context and continue
|
||||
if strings.HasPrefix(l, "msgctxt") {
|
||||
po.parseContext(l)
|
||||
state = msgCtxt
|
||||
continue
|
||||
}
|
||||
|
||||
// Buffer msgid and continue
|
||||
if strings.HasPrefix(l, "msgid") && !strings.HasPrefix(l, "msgid_plural") {
|
||||
po.parseID(l)
|
||||
state = msgID
|
||||
continue
|
||||
}
|
||||
|
||||
// Check for plural form
|
||||
if strings.HasPrefix(l, "msgid_plural") {
|
||||
po.parsePluralID(l)
|
||||
state = msgIDPlural
|
||||
continue
|
||||
}
|
||||
|
||||
// Save translation
|
||||
if strings.HasPrefix(l, "msgstr") {
|
||||
po.parseMessage(l)
|
||||
state = msgStr
|
||||
continue
|
||||
}
|
||||
|
||||
// Multi line strings and headers
|
||||
if strings.HasPrefix(l, "\"") && strings.HasSuffix(l, "\"") {
|
||||
po.parseString(l)
|
||||
state = po.parseString(l, state)
|
||||
continue
|
||||
}
|
||||
}
|
||||
@@ -259,23 +274,36 @@ func (po *Po) parseMessage(l string) {
|
||||
|
||||
// parseString takes a well formatted string without prefix
|
||||
// and creates headers or attach multi-line strings when corresponding
|
||||
func (po *Po) parseString(l string) {
|
||||
// Check for multiline from previously set msgid
|
||||
if po.trBuffer.id != "" {
|
||||
// Append to last translation found
|
||||
func (po *Po) parseString(l string, state parseState) parseState {
|
||||
switch state {
|
||||
case msgStr:
|
||||
// Check for multiline from previously set msgid
|
||||
if po.trBuffer.id != "" {
|
||||
// Append to last translation found
|
||||
uq, _ := strconv.Unquote(l)
|
||||
po.trBuffer.trs[len(po.trBuffer.trs)-1] += uq
|
||||
|
||||
}
|
||||
case msgID:
|
||||
// Multiline msgid - Append to current id
|
||||
uq, _ := strconv.Unquote(l)
|
||||
po.trBuffer.trs[len(po.trBuffer.trs)-1] += uq
|
||||
|
||||
return
|
||||
po.trBuffer.id += uq
|
||||
case msgIDPlural:
|
||||
// Multiline msgid - Append to current id
|
||||
uq, _ := strconv.Unquote(l)
|
||||
po.trBuffer.pluralID += uq
|
||||
case msgCtxt:
|
||||
// Multiline context - Append to current context
|
||||
ctxt, _ := strconv.Unquote(l)
|
||||
po.ctxBuffer += ctxt
|
||||
default:
|
||||
// Otherwise is a header
|
||||
h, _ := strconv.Unquote(strings.TrimSpace(l))
|
||||
po.RawHeaders += h
|
||||
return head
|
||||
}
|
||||
|
||||
// Otherwise is a header
|
||||
h, err := strconv.Unquote(strings.TrimSpace(l))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
po.RawHeaders += h
|
||||
return state
|
||||
}
|
||||
|
||||
// isValidLine checks for line prefixes to detect valid syntax.
|
||||
|
||||
44
po_test.go
44
po_test.go
@@ -9,8 +9,6 @@ import (
|
||||
func TestPo(t *testing.T) {
|
||||
// Set PO content
|
||||
str := `
|
||||
msgid ""
|
||||
msgstr ""
|
||||
# Initial comment
|
||||
# Headers below
|
||||
"Language: en\n"
|
||||
@@ -26,6 +24,19 @@ msgstr "Translated text"
|
||||
msgid "Another string"
|
||||
msgstr ""
|
||||
|
||||
# Multi-line msgid
|
||||
msgid "multi"
|
||||
"line"
|
||||
"id"
|
||||
msgstr "id with multiline content"
|
||||
|
||||
# Multi-line msgid_plural
|
||||
msgid "multi"
|
||||
"line"
|
||||
"plural"
|
||||
"id"
|
||||
msgstr "plural id with multiline content"
|
||||
|
||||
#Multi-line string
|
||||
msgid "Multi-line"
|
||||
msgstr "Multi "
|
||||
@@ -60,7 +71,7 @@ msgstr "Some random translation in a context"
|
||||
|
||||
msgid "More"
|
||||
msgstr "More translation"
|
||||
`
|
||||
`
|
||||
|
||||
// Write PO content to file
|
||||
filename := path.Clean(os.TempDir() + string(os.PathSeparator) + "default.po")
|
||||
@@ -97,6 +108,18 @@ msgstr "More translation"
|
||||
t.Errorf("Expected 'This one is the singular: Variable' but got '%s'", tr)
|
||||
}
|
||||
|
||||
// Test multi-line id
|
||||
tr = po.Get("multilineid")
|
||||
if tr != "id with multiline content" {
|
||||
t.Errorf("Expected 'id with multiline content' but got '%s'", tr)
|
||||
}
|
||||
|
||||
// Test multi-line plural id
|
||||
tr = po.Get("multilinepluralid")
|
||||
if tr != "plural id with multiline content" {
|
||||
t.Errorf("Expected 'plural id with multiline content' but got '%s'", tr)
|
||||
}
|
||||
|
||||
// Test multi-line
|
||||
tr = po.Get("Multi-line")
|
||||
if tr != "Multi line" {
|
||||
@@ -150,13 +173,12 @@ msgstr "More translation"
|
||||
t.Errorf("Expected 'More translation' but got '%s'", tr)
|
||||
}
|
||||
|
||||
t.Log(po.contexts)
|
||||
}
|
||||
|
||||
func TestPoHeaders(t *testing.T) {
|
||||
// Set PO content
|
||||
str := `
|
||||
msgid ""
|
||||
msgstr ""
|
||||
# Initial comment
|
||||
# Headers below
|
||||
"Language: en\n"
|
||||
@@ -167,7 +189,7 @@ msgstr ""
|
||||
# Some comment
|
||||
msgid "Example"
|
||||
msgstr "Translated example"
|
||||
`
|
||||
`
|
||||
|
||||
// Create po object
|
||||
po := new(Po)
|
||||
@@ -198,7 +220,7 @@ msgstr[0] "Singular form"
|
||||
msgstr[1] "Plural form 1"
|
||||
msgstr[2] "Plural form 2"
|
||||
msgstr[3] "Plural form 3"
|
||||
`
|
||||
`
|
||||
|
||||
// Create po object
|
||||
po := new(Po)
|
||||
@@ -241,7 +263,7 @@ msgstr[0] "Singular form"
|
||||
msgstr[1] "Plural form 1"
|
||||
msgstr[2] "Plural form 2"
|
||||
msgstr[3] "Plural form 3"
|
||||
`
|
||||
`
|
||||
|
||||
// Create po object
|
||||
po := new(Po)
|
||||
@@ -280,7 +302,7 @@ msgstr[0] "Singular form"
|
||||
msgstr[1] "Plural form 1"
|
||||
msgstr[2] "Plural form 2"
|
||||
msgstr[3] "Plural form 3"
|
||||
`
|
||||
`
|
||||
|
||||
// Create po object
|
||||
po := new(Po)
|
||||
@@ -328,7 +350,7 @@ msgstr[0] "Singular form"
|
||||
msgstr[1] "Plural form 1"
|
||||
msgstr[2] "Plural form 2"
|
||||
msgstr[3] "Plural form 3"
|
||||
`
|
||||
`
|
||||
|
||||
// Create po object
|
||||
po := new(Po)
|
||||
@@ -394,7 +416,7 @@ msgstr[0] "This one is the singular: %s"
|
||||
msgstr[1] "This one is the plural: %s"
|
||||
msgstr[2] "And this is the second plural form: %s"
|
||||
|
||||
`
|
||||
`
|
||||
|
||||
// Create Po object
|
||||
po := new(Po)
|
||||
|
||||
Reference in New Issue
Block a user