Switch to v1.0.2 of github.com/chai2010/gettext-go

Signed-off-by: Davanum Srinivas <davanum@gmail.com>
This commit is contained in:
Davanum Srinivas
2022-06-10 16:07:52 -04:00
parent f3f50b4d7c
commit 1ff96ede74
38 changed files with 1036 additions and 552 deletions

74
vendor/github.com/chai2010/gettext-go/mo/doc.go generated vendored Normal file
View File

@@ -0,0 +1,74 @@
// Copyright 2013 ChaiShushan <chaishushan{AT}gmail.com>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
Package mo provides support for reading and writing GNU MO file.
Examples:
import (
"github.com/chai2010/gettext-go/mo"
)
func main() {
moFile, err := mo.LoadFile("test.mo")
if err != nil {
log.Fatal(err)
}
fmt.Printf("%v", moFile)
}
GNU MO file struct:
byte
+------------------------------------------+
0 | magic number = 0x950412de |
| |
4 | file format revision = 0 |
| |
8 | number of strings | == N
| |
12 | offset of table with original strings | == O
| |
16 | offset of table with translation strings | == T
| |
20 | size of hashing table | == S
| |
24 | offset of hashing table | == H
| |
. .
. (possibly more entries later) .
. .
| |
O | length & offset 0th string ----------------.
O + 8 | length & offset 1st string ------------------.
... ... | |
O + ((N-1)*8)| length & offset (N-1)th string | | |
| | | |
T | length & offset 0th translation ---------------.
T + 8 | length & offset 1st translation -----------------.
... ... | | | |
T + ((N-1)*8)| length & offset (N-1)th translation | | | | |
| | | | | |
H | start hash table | | | | |
... ... | | | |
H + S * 4 | end hash table | | | | |
| | | | | |
| NUL terminated 0th string <----------------' | | |
| | | | |
| NUL terminated 1st string <------------------' | |
| | | |
... ... | |
| | | |
| NUL terminated 0th translation <---------------' |
| | |
| NUL terminated 1st translation <-----------------'
| |
... ...
| |
+------------------------------------------+
The GNU MO file specification is at
http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html.
*/
package mo

105
vendor/github.com/chai2010/gettext-go/mo/encoder.go generated vendored Normal file
View File

@@ -0,0 +1,105 @@
// Copyright 2013 ChaiShushan <chaishushan{AT}gmail.com>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package mo
import (
"bytes"
"encoding/binary"
"sort"
"strings"
)
type moHeader struct {
MagicNumber uint32
MajorVersion uint16
MinorVersion uint16
MsgIdCount uint32
MsgIdOffset uint32
MsgStrOffset uint32
HashSize uint32
HashOffset uint32
}
type moStrPos struct {
Size uint32 // must keep fields order
Addr uint32
}
func encodeFile(f *File) []byte {
hdr := &moHeader{
MagicNumber: MoMagicLittleEndian,
}
data := encodeData(hdr, f)
data = append(encodeHeader(hdr), data...)
return data
}
// encode data and init moHeader
func encodeData(hdr *moHeader, f *File) []byte {
msgList := []Message{f.MimeHeader.toMessage()}
for _, v := range f.Messages {
if len(v.MsgId) == 0 {
continue
}
if len(v.MsgStr) == 0 && len(v.MsgStrPlural) == 0 {
continue
}
msgList = append(msgList, v)
}
sort.Slice(msgList, func(i, j int) bool {
return msgList[i].less(&msgList[j])
})
var buf bytes.Buffer
var msgIdPosList = make([]moStrPos, len(msgList))
var msgStrPosList = make([]moStrPos, len(msgList))
for i, v := range msgList {
// write msgid
msgId := encodeMsgId(v)
msgIdPosList[i].Addr = uint32(buf.Len() + MoHeaderSize)
msgIdPosList[i].Size = uint32(len(msgId))
buf.WriteString(msgId)
// write msgstr
msgStr := encodeMsgStr(v)
msgStrPosList[i].Addr = uint32(buf.Len() + MoHeaderSize)
msgStrPosList[i].Size = uint32(len(msgStr))
buf.WriteString(msgStr)
}
hdr.MsgIdOffset = uint32(buf.Len() + MoHeaderSize)
binary.Write(&buf, binary.LittleEndian, msgIdPosList)
hdr.MsgStrOffset = uint32(buf.Len() + MoHeaderSize)
binary.Write(&buf, binary.LittleEndian, msgStrPosList)
hdr.MsgIdCount = uint32(len(msgList))
return buf.Bytes()
}
// must called after encodeData
func encodeHeader(hdr *moHeader) []byte {
var buf bytes.Buffer
binary.Write(&buf, binary.LittleEndian, hdr)
return buf.Bytes()
}
func encodeMsgId(v Message) string {
if v.MsgContext != "" && v.MsgIdPlural != "" {
return v.MsgContext + EotSeparator + v.MsgId + NulSeparator + v.MsgIdPlural
}
if v.MsgContext != "" && v.MsgIdPlural == "" {
return v.MsgContext + EotSeparator + v.MsgId
}
if v.MsgContext == "" && v.MsgIdPlural != "" {
return v.MsgId + NulSeparator + v.MsgIdPlural
}
return v.MsgId
}
func encodeMsgStr(v Message) string {
if v.MsgIdPlural != "" {
return strings.Join(v.MsgStrPlural, NulSeparator)
}
return v.MsgStr
}

197
vendor/github.com/chai2010/gettext-go/mo/file.go generated vendored Normal file
View File

@@ -0,0 +1,197 @@
// Copyright 2013 ChaiShushan <chaishushan{AT}gmail.com>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package mo
import (
"bytes"
"encoding/binary"
"fmt"
"io/ioutil"
"strings"
)
const (
MoHeaderSize = 28
MoMagicLittleEndian = 0x950412de
MoMagicBigEndian = 0xde120495
EotSeparator = "\x04" // msgctxt and msgid separator
NulSeparator = "\x00" // msgid and msgstr separator
)
// File represents an MO File.
//
// See http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html
type File struct {
MagicNumber uint32
MajorVersion uint16
MinorVersion uint16
MsgIdCount uint32
MsgIdOffset uint32
MsgStrOffset uint32
HashSize uint32
HashOffset uint32
MimeHeader Header
Messages []Message
}
// Load loads mo file format data.
func Load(data []byte) (*File, error) {
return loadData(data)
}
// Load loads a named mo file.
func LoadFile(path string) (*File, error) {
data, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
return loadData(data)
}
func loadData(data []byte) (*File, error) {
r := bytes.NewReader(data)
var magicNumber uint32
if err := binary.Read(r, binary.LittleEndian, &magicNumber); err != nil {
return nil, fmt.Errorf("gettext: %v", err)
}
var bo binary.ByteOrder
switch magicNumber {
case MoMagicLittleEndian:
bo = binary.LittleEndian
case MoMagicBigEndian:
bo = binary.BigEndian
default:
return nil, fmt.Errorf("gettext: %v", "invalid magic number")
}
var header struct {
MajorVersion uint16
MinorVersion uint16
MsgIdCount uint32
MsgIdOffset uint32
MsgStrOffset uint32
HashSize uint32
HashOffset uint32
}
if err := binary.Read(r, bo, &header); err != nil {
return nil, fmt.Errorf("gettext: %v", err)
}
if v := header.MajorVersion; v != 0 && v != 1 {
return nil, fmt.Errorf("gettext: %v", "invalid version number")
}
if v := header.MinorVersion; v != 0 && v != 1 {
return nil, fmt.Errorf("gettext: %v", "invalid version number")
}
msgIdStart := make([]uint32, header.MsgIdCount)
msgIdLen := make([]uint32, header.MsgIdCount)
if _, err := r.Seek(int64(header.MsgIdOffset), 0); err != nil {
return nil, fmt.Errorf("gettext: %v", err)
}
for i := 0; i < int(header.MsgIdCount); i++ {
if err := binary.Read(r, bo, &msgIdLen[i]); err != nil {
return nil, fmt.Errorf("gettext: %v", err)
}
if err := binary.Read(r, bo, &msgIdStart[i]); err != nil {
return nil, fmt.Errorf("gettext: %v", err)
}
}
msgStrStart := make([]int32, header.MsgIdCount)
msgStrLen := make([]int32, header.MsgIdCount)
if _, err := r.Seek(int64(header.MsgStrOffset), 0); err != nil {
return nil, fmt.Errorf("gettext: %v", err)
}
for i := 0; i < int(header.MsgIdCount); i++ {
if err := binary.Read(r, bo, &msgStrLen[i]); err != nil {
return nil, fmt.Errorf("gettext: %v", err)
}
if err := binary.Read(r, bo, &msgStrStart[i]); err != nil {
return nil, fmt.Errorf("gettext: %v", err)
}
}
file := &File{
MagicNumber: magicNumber,
MajorVersion: header.MajorVersion,
MinorVersion: header.MinorVersion,
MsgIdCount: header.MsgIdCount,
MsgIdOffset: header.MsgIdOffset,
MsgStrOffset: header.MsgStrOffset,
HashSize: header.HashSize,
HashOffset: header.HashOffset,
}
for i := 0; i < int(header.MsgIdCount); i++ {
if _, err := r.Seek(int64(msgIdStart[i]), 0); err != nil {
return nil, fmt.Errorf("gettext: %v", err)
}
msgIdData := make([]byte, msgIdLen[i])
if _, err := r.Read(msgIdData); err != nil {
return nil, fmt.Errorf("gettext: %v", err)
}
if _, err := r.Seek(int64(msgStrStart[i]), 0); err != nil {
return nil, fmt.Errorf("gettext: %v", err)
}
msgStrData := make([]byte, msgStrLen[i])
if _, err := r.Read(msgStrData); err != nil {
return nil, fmt.Errorf("gettext: %v", err)
}
if len(msgIdData) == 0 {
var msg = Message{
MsgId: string(msgIdData),
MsgStr: string(msgStrData),
}
file.MimeHeader.fromMessage(&msg)
} else {
var msg = Message{
MsgId: string(msgIdData),
MsgStr: string(msgStrData),
}
// Is this a context message?
if idx := strings.Index(msg.MsgId, EotSeparator); idx != -1 {
msg.MsgContext, msg.MsgId = msg.MsgId[:idx], msg.MsgId[idx+1:]
}
// Is this a plural message?
if idx := strings.Index(msg.MsgId, NulSeparator); idx != -1 {
msg.MsgId, msg.MsgIdPlural = msg.MsgId[:idx], msg.MsgId[idx+1:]
msg.MsgStrPlural = strings.Split(msg.MsgStr, NulSeparator)
msg.MsgStr = ""
}
file.Messages = append(file.Messages, msg)
}
}
return file, nil
}
// Save saves a mo file.
func (f *File) Save(name string) error {
return ioutil.WriteFile(name, f.Data(), 0666)
}
// Save returns a mo file format data.
func (f *File) Data() []byte {
return encodeFile(f)
}
// String returns the po format file string.
func (f *File) String() string {
var buf bytes.Buffer
fmt.Fprintf(&buf, "# version: %d.%d\n", f.MajorVersion, f.MinorVersion)
fmt.Fprintf(&buf, "%s\n", f.MimeHeader.String())
fmt.Fprintf(&buf, "\n")
for k, v := range f.Messages {
fmt.Fprintf(&buf, `msgid "%v"`+"\n", k)
fmt.Fprintf(&buf, `msgstr "%s"`+"\n", v.MsgStr)
fmt.Fprintf(&buf, "\n")
}
return buf.String()
}

109
vendor/github.com/chai2010/gettext-go/mo/header.go generated vendored Normal file
View File

@@ -0,0 +1,109 @@
// Copyright 2013 ChaiShushan <chaishushan{AT}gmail.com>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package mo
import (
"bytes"
"fmt"
"strings"
)
// Header is the initial comments "SOME DESCRIPTIVE TITLE", "YEAR"
// and "FIRST AUTHOR <EMAIL@ADDRESS>, YEAR" ought to be replaced by sensible information.
//
// See http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html#Header-Entry
type Header struct {
ProjectIdVersion string // Project-Id-Version: PACKAGE VERSION
ReportMsgidBugsTo string // Report-Msgid-Bugs-To: FIRST AUTHOR <EMAIL@ADDRESS>
POTCreationDate string // POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE
PORevisionDate string // PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE
LastTranslator string // Last-Translator: FIRST AUTHOR <EMAIL@ADDRESS>
LanguageTeam string // Language-Team: golang-china
Language string // Language: zh_CN
MimeVersion string // MIME-Version: 1.0
ContentType string // Content-Type: text/plain; charset=UTF-8
ContentTransferEncoding string // Content-Transfer-Encoding: 8bit
PluralForms string // Plural-Forms: nplurals=2; plural=n == 1 ? 0 : 1;
XGenerator string // X-Generator: Poedit 1.5.5
UnknowFields map[string]string
}
func (p *Header) fromMessage(msg *Message) {
if msg.MsgId != "" || msg.MsgStr == "" {
return
}
lines := strings.Split(msg.MsgStr, "\n")
for i := 0; i < len(lines); i++ {
idx := strings.Index(lines[i], ":")
if idx < 0 {
continue
}
key := strings.TrimSpace(lines[i][:idx])
val := strings.TrimSpace(lines[i][idx+1:])
switch strings.ToUpper(key) {
case strings.ToUpper("Project-Id-Version"):
p.ProjectIdVersion = val
case strings.ToUpper("Report-Msgid-Bugs-To"):
p.ReportMsgidBugsTo = val
case strings.ToUpper("POT-Creation-Date"):
p.POTCreationDate = val
case strings.ToUpper("PO-Revision-Date"):
p.PORevisionDate = val
case strings.ToUpper("Last-Translator"):
p.LastTranslator = val
case strings.ToUpper("Language-Team"):
p.LanguageTeam = val
case strings.ToUpper("Language"):
p.Language = val
case strings.ToUpper("MIME-Version"):
p.MimeVersion = val
case strings.ToUpper("Content-Type"):
p.ContentType = val
case strings.ToUpper("Content-Transfer-Encoding"):
p.ContentTransferEncoding = val
case strings.ToUpper("Plural-Forms"):
p.PluralForms = val
case strings.ToUpper("X-Generator"):
p.XGenerator = val
default:
if p.UnknowFields == nil {
p.UnknowFields = make(map[string]string)
}
p.UnknowFields[key] = val
}
}
}
func (p *Header) toMessage() Message {
return Message{
MsgStr: p.String(),
}
}
// String returns the po format header string.
func (p Header) String() string {
var buf bytes.Buffer
fmt.Fprintf(&buf, `msgid ""`+"\n")
fmt.Fprintf(&buf, `msgstr ""`+"\n")
fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "Project-Id-Version", p.ProjectIdVersion)
fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "Report-Msgid-Bugs-To", p.ReportMsgidBugsTo)
fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "POT-Creation-Date", p.POTCreationDate)
fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "PO-Revision-Date", p.PORevisionDate)
fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "Last-Translator", p.LastTranslator)
fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "Language-Team", p.LanguageTeam)
fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "Language", p.Language)
if p.MimeVersion != "" {
fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "MIME-Version", p.MimeVersion)
}
fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "Content-Type", p.ContentType)
fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "Content-Transfer-Encoding", p.ContentTransferEncoding)
if p.XGenerator != "" {
fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", "X-Generator", p.XGenerator)
}
for k, v := range p.UnknowFields {
fmt.Fprintf(&buf, `"%s: %s\n"`+"\n", k, v)
}
return buf.String()
}

52
vendor/github.com/chai2010/gettext-go/mo/message.go generated vendored Normal file
View File

@@ -0,0 +1,52 @@
// Copyright 2013 ChaiShushan <chaishushan{AT}gmail.com>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package mo
import (
"bytes"
"fmt"
)
// A MO file is made up of many entries,
// each entry holding the relation between an original untranslated string
// and its corresponding translation.
//
// See http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html
type Message struct {
MsgContext string // msgctxt context
MsgId string // msgid untranslated-string
MsgIdPlural string // msgid_plural untranslated-string-plural
MsgStr string // msgstr translated-string
MsgStrPlural []string // msgstr[0] translated-string-case-0
}
// String returns the po format entry string.
func (p Message) String() string {
var buf bytes.Buffer
fmt.Fprintf(&buf, "msgid %s", encodePoString(p.MsgId))
if p.MsgIdPlural != "" {
fmt.Fprintf(&buf, "msgid_plural %s", encodePoString(p.MsgIdPlural))
}
if p.MsgStr != "" {
fmt.Fprintf(&buf, "msgstr %s", encodePoString(p.MsgStr))
}
for i := 0; i < len(p.MsgStrPlural); i++ {
fmt.Fprintf(&buf, "msgstr[%d] %s", i, encodePoString(p.MsgStrPlural[i]))
}
return buf.String()
}
func (m_i *Message) less(m_j *Message) bool {
if a, b := m_i.MsgContext, m_j.MsgContext; a != b {
return a < b
}
if a, b := m_i.MsgId, m_j.MsgId; a != b {
return a < b
}
if a, b := m_i.MsgIdPlural, m_j.MsgIdPlural; a != b {
return a < b
}
return false
}

110
vendor/github.com/chai2010/gettext-go/mo/util.go generated vendored Normal file
View File

@@ -0,0 +1,110 @@
// Copyright 2013 ChaiShushan <chaishushan{AT}gmail.com>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package mo
import (
"bytes"
"strings"
)
func decodePoString(text string) string {
lines := strings.Split(text, "\n")
for i := 0; i < len(lines); i++ {
left := strings.Index(lines[i], `"`)
right := strings.LastIndex(lines[i], `"`)
if left < 0 || right < 0 || left == right {
lines[i] = ""
continue
}
line := lines[i][left+1 : right]
data := make([]byte, 0, len(line))
for i := 0; i < len(line); i++ {
if line[i] != '\\' {
data = append(data, line[i])
continue
}
if i+1 >= len(line) {
break
}
switch line[i+1] {
case 'n': // \\n -> \n
data = append(data, '\n')
i++
case 't': // \\t -> \n
data = append(data, '\t')
i++
case '\\': // \\\ -> ?
data = append(data, '\\')
i++
}
}
lines[i] = string(data)
}
return strings.Join(lines, "")
}
func encodePoString(text string) string {
var buf bytes.Buffer
lines := strings.Split(text, "\n")
for i := 0; i < len(lines); i++ {
if lines[i] == "" {
if i != len(lines)-1 {
buf.WriteString(`"\n"` + "\n")
}
continue
}
buf.WriteRune('"')
for _, r := range lines[i] {
switch r {
case '\\':
buf.WriteString(`\\`)
case '"':
buf.WriteString(`\"`)
case '\n':
buf.WriteString(`\n`)
case '\t':
buf.WriteString(`\t`)
default:
buf.WriteRune(r)
}
}
buf.WriteString(`\n"` + "\n")
}
return buf.String()
}
func encodeCommentPoString(text string) string {
var buf bytes.Buffer
lines := strings.Split(text, "\n")
if len(lines) > 1 {
buf.WriteString(`""` + "\n")
}
for i := 0; i < len(lines); i++ {
if len(lines) > 0 {
buf.WriteString("#| ")
}
buf.WriteRune('"')
for _, r := range lines[i] {
switch r {
case '\\':
buf.WriteString(`\\`)
case '"':
buf.WriteString(`\"`)
case '\n':
buf.WriteString(`\n`)
case '\t':
buf.WriteString(`\t`)
default:
buf.WriteRune(r)
}
}
if i < len(lines)-1 {
buf.WriteString(`\n"` + "\n")
} else {
buf.WriteString(`"`)
}
}
return buf.String()
}