Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
6dd760d3
Commit
6dd760d3
authored
Dec 13, 2016
by
Brendan Burns
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add github.com/chai2010/gettext-go dependency
parent
b3e57253
Hide whitespace changes
Inline
Side-by-side
Showing
30 changed files
with
2885 additions
and
0 deletions
+2885
-0
Godeps.json
Godeps/Godeps.json
+16
-0
LICENSES
Godeps/LICENSES
+140
-0
BUILD
vendor/BUILD
+58
-0
LICENSE
vendor/github.com/chai2010/gettext-go/LICENSE
+27
-0
caller.go
vendor/github.com/chai2010/gettext-go/gettext/caller.go
+39
-0
doc.go
vendor/github.com/chai2010/gettext-go/gettext/doc.go
+66
-0
domain.go
vendor/github.com/chai2010/gettext-go/gettext/domain.go
+119
-0
domain_helper.go
...r/github.com/chai2010/gettext-go/gettext/domain_helper.go
+50
-0
fs.go
vendor/github.com/chai2010/gettext-go/gettext/fs.go
+187
-0
gettext.go
vendor/github.com/chai2010/gettext-go/gettext/gettext.go
+184
-0
hello.go
vendor/github.com/chai2010/gettext-go/gettext/hello.go
+22
-0
local.go
vendor/github.com/chai2010/gettext-go/gettext/local.go
+34
-0
doc.go
vendor/github.com/chai2010/gettext-go/gettext/mo/doc.go
+74
-0
encoder.go
vendor/github.com/chai2010/gettext-go/gettext/mo/encoder.go
+124
-0
file.go
vendor/github.com/chai2010/gettext-go/gettext/mo/file.go
+193
-0
header.go
vendor/github.com/chai2010/gettext-go/gettext/mo/header.go
+109
-0
message.go
vendor/github.com/chai2010/gettext-go/gettext/mo/message.go
+39
-0
util.go
vendor/github.com/chai2010/gettext-go/gettext/mo/util.go
+110
-0
doc.go
vendor/github.com/chai2010/gettext-go/gettext/plural/doc.go
+36
-0
formula.go
.../github.com/chai2010/gettext-go/gettext/plural/formula.go
+181
-0
table.go
...or/github.com/chai2010/gettext-go/gettext/plural/table.go
+55
-0
comment.go
vendor/github.com/chai2010/gettext-go/gettext/po/comment.go
+270
-0
doc.go
vendor/github.com/chai2010/gettext-go/gettext/po/doc.go
+24
-0
file.go
vendor/github.com/chai2010/gettext-go/gettext/po/file.go
+75
-0
header.go
vendor/github.com/chai2010/gettext-go/gettext/po/header.go
+106
-0
line_reader.go
.../github.com/chai2010/gettext-go/gettext/po/line_reader.go
+62
-0
message.go
vendor/github.com/chai2010/gettext-go/gettext/po/message.go
+189
-0
re.go
vendor/github.com/chai2010/gettext-go/gettext/po/re.go
+58
-0
util.go
vendor/github.com/chai2010/gettext-go/gettext/po/util.go
+110
-0
tr.go
vendor/github.com/chai2010/gettext-go/gettext/tr.go
+128
-0
No files found.
Godeps/Godeps.json
View file @
6dd760d3
...
@@ -288,6 +288,22 @@
...
@@ -288,6 +288,22 @@
"Rev"
:
"dfb21201d9270c1082d5fb0f07f500311ff72f18"
"Rev"
:
"dfb21201d9270c1082d5fb0f07f500311ff72f18"
},
},
{
{
"ImportPath"
:
"github.com/chai2010/gettext-go/gettext"
,
"Rev"
:
"c6fed771bfd517099caf0f7a961671fa8ed08723"
},
{
"ImportPath"
:
"github.com/chai2010/gettext-go/gettext/mo"
,
"Rev"
:
"c6fed771bfd517099caf0f7a961671fa8ed08723"
},
{
"ImportPath"
:
"github.com/chai2010/gettext-go/gettext/plural"
,
"Rev"
:
"c6fed771bfd517099caf0f7a961671fa8ed08723"
},
{
"ImportPath"
:
"github.com/chai2010/gettext-go/gettext/po"
,
"Rev"
:
"c6fed771bfd517099caf0f7a961671fa8ed08723"
},
{
"ImportPath"
:
"github.com/cloudflare/cfssl/auth"
,
"ImportPath"
:
"github.com/cloudflare/cfssl/auth"
,
"Comment"
:
"1.2.0"
,
"Comment"
:
"1.2.0"
,
"Rev"
:
"db0d0650b6496bfe8061ec56a92edd32d8e75c30"
"Rev"
:
"db0d0650b6496bfe8061ec56a92edd32d8e75c30"
...
...
Godeps/LICENSES
View file @
6dd760d3
...
@@ -9644,6 +9644,146 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
...
@@ -9644,6 +9644,146 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================================================
================================================================================
= vendor/github.com/chai2010/gettext-go/gettext licensed under: =
Copyright 2013 ChaiShushan <chaishushan{AT}gmail.com>. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
= vendor/github.com/chai2010/gettext-go/LICENSE 87ce3ee0376881b02e75d3d5be2a6ba6 -
================================================================================
================================================================================
= vendor/github.com/chai2010/gettext-go/gettext/mo licensed under: =
Copyright 2013 ChaiShushan <chaishushan{AT}gmail.com>. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
= vendor/github.com/chai2010/gettext-go/LICENSE 87ce3ee0376881b02e75d3d5be2a6ba6 -
================================================================================
================================================================================
= vendor/github.com/chai2010/gettext-go/gettext/plural licensed under: =
Copyright 2013 ChaiShushan <chaishushan{AT}gmail.com>. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
= vendor/github.com/chai2010/gettext-go/LICENSE 87ce3ee0376881b02e75d3d5be2a6ba6 -
================================================================================
================================================================================
= vendor/github.com/chai2010/gettext-go/gettext/po licensed under: =
Copyright 2013 ChaiShushan <chaishushan{AT}gmail.com>. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
= vendor/github.com/chai2010/gettext-go/LICENSE 87ce3ee0376881b02e75d3d5be2a6ba6 -
================================================================================
================================================================================
= vendor/github.com/cloudflare/cfssl/auth licensed under: =
= vendor/github.com/cloudflare/cfssl/auth licensed under: =
Copyright (c) 2014 CloudFlare Inc.
Copyright (c) 2014 CloudFlare Inc.
vendor/BUILD
View file @
6dd760d3
...
@@ -803,6 +803,64 @@ go_library(
...
@@ -803,6 +803,64 @@ go_library(
)
)
go_library(
go_library(
name = "github.com/chai2010/gettext-go/gettext",
srcs = [
"github.com/chai2010/gettext-go/gettext/caller.go",
"github.com/chai2010/gettext-go/gettext/doc.go",
"github.com/chai2010/gettext-go/gettext/domain.go",
"github.com/chai2010/gettext-go/gettext/domain_helper.go",
"github.com/chai2010/gettext-go/gettext/fs.go",
"github.com/chai2010/gettext-go/gettext/gettext.go",
"github.com/chai2010/gettext-go/gettext/local.go",
"github.com/chai2010/gettext-go/gettext/tr.go",
],
tags = ["automanaged"],
deps = [
"//vendor:github.com/chai2010/gettext-go/gettext/mo",
"//vendor:github.com/chai2010/gettext-go/gettext/plural",
"//vendor:github.com/chai2010/gettext-go/gettext/po",
],
)
go_library(
name = "github.com/chai2010/gettext-go/gettext/mo",
srcs = [
"github.com/chai2010/gettext-go/gettext/mo/doc.go",
"github.com/chai2010/gettext-go/gettext/mo/encoder.go",
"github.com/chai2010/gettext-go/gettext/mo/file.go",
"github.com/chai2010/gettext-go/gettext/mo/header.go",
"github.com/chai2010/gettext-go/gettext/mo/message.go",
"github.com/chai2010/gettext-go/gettext/mo/util.go",
],
tags = ["automanaged"],
)
go_library(
name = "github.com/chai2010/gettext-go/gettext/plural",
srcs = [
"github.com/chai2010/gettext-go/gettext/plural/doc.go",
"github.com/chai2010/gettext-go/gettext/plural/formula.go",
"github.com/chai2010/gettext-go/gettext/plural/table.go",
],
tags = ["automanaged"],
)
go_library(
name = "github.com/chai2010/gettext-go/gettext/po",
srcs = [
"github.com/chai2010/gettext-go/gettext/po/comment.go",
"github.com/chai2010/gettext-go/gettext/po/doc.go",
"github.com/chai2010/gettext-go/gettext/po/file.go",
"github.com/chai2010/gettext-go/gettext/po/header.go",
"github.com/chai2010/gettext-go/gettext/po/line_reader.go",
"github.com/chai2010/gettext-go/gettext/po/message.go",
"github.com/chai2010/gettext-go/gettext/po/re.go",
"github.com/chai2010/gettext-go/gettext/po/util.go",
],
tags = ["automanaged"],
)
go_library(
name = "github.com/cloudflare/cfssl/auth",
name = "github.com/cloudflare/cfssl/auth",
srcs = ["github.com/cloudflare/cfssl/auth/auth.go"],
srcs = ["github.com/cloudflare/cfssl/auth/auth.go"],
tags = ["automanaged"],
tags = ["automanaged"],
...
...
vendor/github.com/chai2010/gettext-go/LICENSE
0 → 100644
View file @
6dd760d3
Copyright 2013 ChaiShushan <chaishushan{AT}gmail.com>. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
vendor/github.com/chai2010/gettext-go/gettext/caller.go
0 → 100644
View file @
6dd760d3
// 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
gettext
import
(
"regexp"
"runtime"
)
var
(
reInit
=
regexp
.
MustCompile
(
`init·\d+$`
)
// main.init·1
reClosure
=
regexp
.
MustCompile
(
`func·\d+$`
)
// main.func·001
)
// caller types:
// runtime.goexit
// runtime.main
// main.init
// main.main
// main.init·1 -> main.init
// main.func·001 -> main.func
// code.google.com/p/gettext-go/gettext.TestCallerName
// ...
func
callerName
(
skip
int
)
string
{
pc
,
_
,
_
,
ok
:=
runtime
.
Caller
(
skip
)
if
!
ok
{
return
""
}
name
:=
runtime
.
FuncForPC
(
pc
)
.
Name
()
if
reInit
.
MatchString
(
name
)
{
return
reInit
.
ReplaceAllString
(
name
,
"init"
)
}
if
reClosure
.
MatchString
(
name
)
{
return
reClosure
.
ReplaceAllString
(
name
,
"func"
)
}
return
name
}
vendor/github.com/chai2010/gettext-go/gettext/doc.go
0 → 100644
View file @
6dd760d3
// Copyright 2013 <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 gettext implements a basic GNU's gettext library.
Example:
import (
"github.com/chai2010/gettext-go/gettext"
)
func main() {
gettext.SetLocale("zh_CN")
gettext.Textdomain("hello")
// gettext.BindTextdomain("hello", "local", nil) // from local dir
// gettext.BindTextdomain("hello", "local.zip", nil) // from local zip file
// gettext.BindTextdomain("hello", "local.zip", zipData) // from embedded zip data
gettext.BindTextdomain("hello", "local", nil)
// translate source text
fmt.Println(gettext.Gettext("Hello, world!"))
// Output: 你好, 世界!
// translate resource
fmt.Println(string(gettext.Getdata("poems.txt")))
// Output: ...
}
Translate directory struct("../examples/local.zip"):
Root: "path" or "file.zip/zipBaseName"
+-default # local: $(LC_MESSAGES) or $(LANG) or "default"
| +-LC_MESSAGES # just for `gettext.Gettext`
| | +-hello.mo # $(Root)/$(local)/LC_MESSAGES/$(domain).mo
| | \-hello.po # $(Root)/$(local)/LC_MESSAGES/$(domain).mo
| |
| \-LC_RESOURCE # just for `gettext.Getdata`
| +-hello # domain map a dir in resource translate
| +-favicon.ico # $(Root)/$(local)/LC_RESOURCE/$(domain)/$(filename)
| \-poems.txt
|
\-zh_CN # simple chinese translate
+-LC_MESSAGES
| +-hello.mo # try "$(domain).mo" first
| \-hello.po # try "$(domain).po" second
|
\-LC_RESOURCE
+-hello
+-favicon.ico # try "$(local)/$(domain)/file" first
\-poems.txt # try "default/$(domain)/file" second
See:
http://en.wikipedia.org/wiki/Gettext
http://www.gnu.org/software/gettext/manual/html_node
http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html
http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html
http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html
http://www.poedit.net/
Please report bugs to <chaishushan{AT}gmail.com>.
Thanks!
*/
package
gettext
vendor/github.com/chai2010/gettext-go/gettext/domain.go
0 → 100644
View file @
6dd760d3
// 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
gettext
import
(
"sync"
)
type
domainManager
struct
{
mutex
sync
.
Mutex
locale
string
domain
string
domainMap
map
[
string
]
*
fileSystem
trTextMap
map
[
string
]
*
translator
}
func
newDomainManager
()
*
domainManager
{
return
&
domainManager
{
locale
:
DefaultLocale
,
domainMap
:
make
(
map
[
string
]
*
fileSystem
),
trTextMap
:
make
(
map
[
string
]
*
translator
),
}
}
func
(
p
*
domainManager
)
makeTrMapKey
(
domain
,
locale
string
)
string
{
return
domain
+
"_$$$_"
+
locale
}
func
(
p
*
domainManager
)
Bind
(
domain
,
path
string
,
data
[]
byte
)
(
domains
,
paths
[]
string
)
{
p
.
mutex
.
Lock
()
defer
p
.
mutex
.
Unlock
()
switch
{
case
domain
!=
""
&&
path
!=
""
:
// bind new domain
p
.
bindDomainTranslators
(
domain
,
path
,
data
)
case
domain
!=
""
&&
path
==
""
:
// delete domain
p
.
deleteDomain
(
domain
)
}
// return all bind domain
for
k
,
fs
:=
range
p
.
domainMap
{
domains
=
append
(
domains
,
k
)
paths
=
append
(
paths
,
fs
.
FsName
)
}
return
}
func
(
p
*
domainManager
)
SetLocale
(
locale
string
)
string
{
p
.
mutex
.
Lock
()
defer
p
.
mutex
.
Unlock
()
if
locale
!=
""
{
p
.
locale
=
locale
}
return
p
.
locale
}
func
(
p
*
domainManager
)
SetDomain
(
domain
string
)
string
{
p
.
mutex
.
Lock
()
defer
p
.
mutex
.
Unlock
()
if
domain
!=
""
{
p
.
domain
=
domain
}
return
p
.
domain
}
func
(
p
*
domainManager
)
Getdata
(
name
string
)
[]
byte
{
return
p
.
getdata
(
p
.
domain
,
name
)
}
func
(
p
*
domainManager
)
DGetdata
(
domain
,
name
string
)
[]
byte
{
return
p
.
getdata
(
domain
,
name
)
}
func
(
p
*
domainManager
)
PNGettext
(
msgctxt
,
msgid
,
msgidPlural
string
,
n
int
)
string
{
p
.
mutex
.
Lock
()
defer
p
.
mutex
.
Unlock
()
return
p
.
gettext
(
p
.
domain
,
msgctxt
,
msgid
,
msgidPlural
,
n
)
}
func
(
p
*
domainManager
)
DPNGettext
(
domain
,
msgctxt
,
msgid
,
msgidPlural
string
,
n
int
)
string
{
p
.
mutex
.
Lock
()
defer
p
.
mutex
.
Unlock
()
return
p
.
gettext
(
domain
,
msgctxt
,
msgid
,
msgidPlural
,
n
)
}
func
(
p
*
domainManager
)
gettext
(
domain
,
msgctxt
,
msgid
,
msgidPlural
string
,
n
int
)
string
{
if
p
.
locale
==
""
||
p
.
domain
==
""
{
return
msgid
}
if
_
,
ok
:=
p
.
domainMap
[
domain
];
!
ok
{
return
msgid
}
if
f
,
ok
:=
p
.
trTextMap
[
p
.
makeTrMapKey
(
domain
,
p
.
locale
)];
ok
{
return
f
.
PNGettext
(
msgctxt
,
msgid
,
msgidPlural
,
n
)
}
return
msgid
}
func
(
p
*
domainManager
)
getdata
(
domain
,
name
string
)
[]
byte
{
if
p
.
locale
==
""
||
p
.
domain
==
""
{
return
nil
}
if
_
,
ok
:=
p
.
domainMap
[
domain
];
!
ok
{
return
nil
}
if
fs
,
ok
:=
p
.
domainMap
[
domain
];
ok
{
if
data
,
err
:=
fs
.
LoadResourceFile
(
domain
,
p
.
locale
,
name
);
err
==
nil
{
return
data
}
if
p
.
locale
!=
"default"
{
if
data
,
err
:=
fs
.
LoadResourceFile
(
domain
,
"default"
,
name
);
err
==
nil
{
return
data
}
}
}
return
nil
}
vendor/github.com/chai2010/gettext-go/gettext/domain_helper.go
0 → 100644
View file @
6dd760d3
// 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
gettext
import
(
"fmt"
"strings"
)
func
(
p
*
domainManager
)
bindDomainTranslators
(
domain
,
path
string
,
data
[]
byte
)
{
if
_
,
ok
:=
p
.
domainMap
[
domain
];
ok
{
p
.
deleteDomain
(
domain
)
// delete old domain
}
fs
:=
newFileSystem
(
path
,
data
)
for
locale
,
_
:=
range
fs
.
LocaleMap
{
trMapKey
:=
p
.
makeTrMapKey
(
domain
,
locale
)
if
data
,
err
:=
fs
.
LoadMessagesFile
(
domain
,
locale
,
".mo"
);
err
==
nil
{
p
.
trTextMap
[
trMapKey
],
_
=
newMoTranslator
(
fmt
.
Sprintf
(
"%s_%s.mo"
,
domain
,
locale
),
data
,
)
continue
}
if
data
,
err
:=
fs
.
LoadMessagesFile
(
domain
,
locale
,
".po"
);
err
==
nil
{
p
.
trTextMap
[
trMapKey
],
_
=
newPoTranslator
(
fmt
.
Sprintf
(
"%s_%s.po"
,
domain
,
locale
),
data
,
)
continue
}
p
.
trTextMap
[
p
.
makeTrMapKey
(
domain
,
locale
)]
=
nilTranslator
}
p
.
domainMap
[
domain
]
=
fs
}
func
(
p
*
domainManager
)
deleteDomain
(
domain
string
)
{
if
_
,
ok
:=
p
.
domainMap
[
domain
];
!
ok
{
return
}
// delete all mo files
trMapKeyPrefix
:=
p
.
makeTrMapKey
(
domain
,
""
)
for
k
,
_
:=
range
p
.
trTextMap
{
if
strings
.
HasPrefix
(
k
,
trMapKeyPrefix
)
{
delete
(
p
.
trTextMap
,
k
)
}
}
delete
(
p
.
domainMap
,
domain
)
}
vendor/github.com/chai2010/gettext-go/gettext/fs.go
0 → 100644
View file @
6dd760d3
// 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
gettext
import
(
"archive/zip"
"bytes"
"fmt"
"io/ioutil"
"log"
"os"
"strings"
)
type
fileSystem
struct
{
FsName
string
FsRoot
string
FsZipData
[]
byte
LocaleMap
map
[
string
]
bool
}
func
newFileSystem
(
path
string
,
data
[]
byte
)
*
fileSystem
{
fs
:=
&
fileSystem
{
FsName
:
path
,
FsZipData
:
data
,
}
if
err
:=
fs
.
init
();
err
!=
nil
{
log
.
Printf
(
"gettext-go: invalid domain, err = %v"
,
err
)
}
return
fs
}
func
(
p
*
fileSystem
)
init
()
error
{
zipName
:=
func
(
name
string
)
string
{
if
x
:=
strings
.
LastIndexAny
(
name
,
`\/`
);
x
!=
-
1
{
name
=
name
[
x
+
1
:
]
}
name
=
strings
.
TrimSuffix
(
name
,
".zip"
)
return
name
}
// zip data
if
len
(
p
.
FsZipData
)
!=
0
{
p
.
FsRoot
=
zipName
(
p
.
FsName
)
p
.
LocaleMap
=
p
.
lsZip
(
p
.
FsZipData
)
return
nil
}
// local dir or zip file
fi
,
err
:=
os
.
Stat
(
p
.
FsName
)
if
err
!=
nil
{
return
err
}
// local dir
if
fi
.
IsDir
()
{
p
.
FsRoot
=
p
.
FsName
p
.
LocaleMap
=
p
.
lsDir
(
p
.
FsName
)
return
nil
}
// local zip file
p
.
FsZipData
,
err
=
ioutil
.
ReadFile
(
p
.
FsName
)
if
err
!=
nil
{
return
err
}
p
.
FsRoot
=
zipName
(
p
.
FsName
)
p
.
LocaleMap
=
p
.
lsZip
(
p
.
FsZipData
)
return
nil
}
func
(
p
*
fileSystem
)
LoadMessagesFile
(
domain
,
local
,
ext
string
)
([]
byte
,
error
)
{
if
len
(
p
.
FsZipData
)
==
0
{
trName
:=
p
.
makeMessagesFileName
(
domain
,
local
,
ext
)
rcData
,
err
:=
ioutil
.
ReadFile
(
trName
)
if
err
!=
nil
{
return
nil
,
err
}
return
rcData
,
nil
}
else
{
r
,
err
:=
zip
.
NewReader
(
bytes
.
NewReader
(
p
.
FsZipData
),
int64
(
len
(
p
.
FsZipData
)))
if
err
!=
nil
{
return
nil
,
err
}
trName
:=
p
.
makeMessagesFileName
(
domain
,
local
,
ext
)
for
_
,
f
:=
range
r
.
File
{
if
f
.
Name
!=
trName
{
continue
}
rc
,
err
:=
f
.
Open
()
if
err
!=
nil
{
return
nil
,
err
}
rcData
,
err
:=
ioutil
.
ReadAll
(
rc
)
rc
.
Close
()
return
rcData
,
err
}
return
nil
,
fmt
.
Errorf
(
"not found"
)
}
}
func
(
p
*
fileSystem
)
LoadResourceFile
(
domain
,
local
,
name
string
)
([]
byte
,
error
)
{
if
len
(
p
.
FsZipData
)
==
0
{
rcName
:=
p
.
makeResourceFileName
(
domain
,
local
,
name
)
rcData
,
err
:=
ioutil
.
ReadFile
(
rcName
)
if
err
!=
nil
{
return
nil
,
err
}
return
rcData
,
nil
}
else
{
r
,
err
:=
zip
.
NewReader
(
bytes
.
NewReader
(
p
.
FsZipData
),
int64
(
len
(
p
.
FsZipData
)))
if
err
!=
nil
{
return
nil
,
err
}
rcName
:=
p
.
makeResourceFileName
(
domain
,
local
,
name
)
for
_
,
f
:=
range
r
.
File
{
if
f
.
Name
!=
rcName
{
continue
}
rc
,
err
:=
f
.
Open
()
if
err
!=
nil
{
return
nil
,
err
}
rcData
,
err
:=
ioutil
.
ReadAll
(
rc
)
rc
.
Close
()
return
rcData
,
err
}
return
nil
,
fmt
.
Errorf
(
"not found"
)
}
}
func
(
p
*
fileSystem
)
makeMessagesFileName
(
domain
,
local
,
ext
string
)
string
{
return
fmt
.
Sprintf
(
"%s/%s/LC_MESSAGES/%s%s"
,
p
.
FsRoot
,
local
,
domain
,
ext
)
}
func
(
p
*
fileSystem
)
makeResourceFileName
(
domain
,
local
,
name
string
)
string
{
return
fmt
.
Sprintf
(
"%s/%s/LC_RESOURCE/%s/%s"
,
p
.
FsRoot
,
local
,
domain
,
name
)
}
func
(
p
*
fileSystem
)
lsZip
(
data
[]
byte
)
map
[
string
]
bool
{
r
,
err
:=
zip
.
NewReader
(
bytes
.
NewReader
(
data
),
int64
(
len
(
data
)))
if
err
!=
nil
{
return
nil
}
ssMap
:=
make
(
map
[
string
]
bool
)
for
_
,
f
:=
range
r
.
File
{
if
x
:=
strings
.
Index
(
f
.
Name
,
"LC_MESSAGES"
);
x
!=
-
1
{
s
:=
strings
.
TrimRight
(
f
.
Name
[
:
x
],
`\/`
)
if
x
=
strings
.
LastIndexAny
(
s
,
`\/`
);
x
!=
-
1
{
s
=
s
[
x
+
1
:
]
}
if
s
!=
""
{
ssMap
[
s
]
=
true
}
continue
}
if
x
:=
strings
.
Index
(
f
.
Name
,
"LC_RESOURCE"
);
x
!=
-
1
{
s
:=
strings
.
TrimRight
(
f
.
Name
[
:
x
],
`\/`
)
if
x
=
strings
.
LastIndexAny
(
s
,
`\/`
);
x
!=
-
1
{
s
=
s
[
x
+
1
:
]
}
if
s
!=
""
{
ssMap
[
s
]
=
true
}
continue
}
}
return
ssMap
}
func
(
p
*
fileSystem
)
lsDir
(
path
string
)
map
[
string
]
bool
{
list
,
err
:=
ioutil
.
ReadDir
(
path
)
if
err
!=
nil
{
return
nil
}
ssMap
:=
make
(
map
[
string
]
bool
)
for
_
,
dir
:=
range
list
{
if
dir
.
IsDir
()
{
ssMap
[
dir
.
Name
()]
=
true
}
}
return
ssMap
}
vendor/github.com/chai2010/gettext-go/gettext/gettext.go
0 → 100644
View file @
6dd760d3
// 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
gettext
var
(
defaultManager
=
newDomainManager
()
)
var
(
DefaultLocale
=
getDefaultLocale
()
// use $(LC_MESSAGES) or $(LANG) or "default"
)
// SetLocale sets and queries the program's current locale.
//
// If the locale is not empty string, set the new local.
//
// If the locale is empty string, don't change anything.
//
// Returns is the current locale.
//
// Examples:
// SetLocale("") // get locale: return DefaultLocale
// SetLocale("zh_CN") // set locale: return zh_CN
// SetLocale("") // get locale: return zh_CN
func
SetLocale
(
locale
string
)
string
{
return
defaultManager
.
SetLocale
(
locale
)
}
// BindTextdomain sets and queries program's domains.
//
// If the domain and path are all not empty string, bind the new domain.
// If the domain already exists, return error.
//
// If the domain is not empty string, but the path is the empty string,
// delete the domain.
// If the domain don't exists, return error.
//
// If the domain and the path are all empty string, don't change anything.
//
// Returns is the all bind domains.
//
// Examples:
// BindTextdomain("poedit", "local", nil) // bind "poedit" domain
// BindTextdomain("", "", nil) // return all domains
// BindTextdomain("poedit", "", nil) // delete "poedit" domain
// BindTextdomain("", "", nil) // return all domains
//
// Use zip file:
// BindTextdomain("poedit", "local.zip", nil) // bind "poedit" domain
// BindTextdomain("poedit", "local.zip", zipData) // bind "poedit" domain
//
func
BindTextdomain
(
domain
,
path
string
,
zipData
[]
byte
)
(
domains
,
paths
[]
string
)
{
return
defaultManager
.
Bind
(
domain
,
path
,
zipData
)
}
// Textdomain sets and retrieves the current message domain.
//
// If the domain is not empty string, set the new domains.
//
// If the domain is empty string, don't change anything.
//
// Returns is the all used domains.
//
// Examples:
// Textdomain("poedit") // set domain: poedit
// Textdomain("") // get domain: return poedit
func
Textdomain
(
domain
string
)
string
{
return
defaultManager
.
SetDomain
(
domain
)
}
// Gettext attempt to translate a text string into the user's native language,
// by looking up the translation in a message catalog.
//
// It use the caller's function name as the msgctxt.
//
// Examples:
// func Foo() {
// msg := gettext.Gettext("Hello") // msgctxt is "some/package/name.Foo"
// }
func
Gettext
(
msgid
string
)
string
{
return
PGettext
(
callerName
(
2
),
msgid
)
}
// Getdata attempt to translate a resource file into the user's native language,
// by looking up the translation in a message catalog.
//
// Examples:
// func Foo() {
// Textdomain("hello")
// BindTextdomain("hello", "local.zip", nilOrZipData)
// poems := gettext.Getdata("poems.txt")
// }
func
Getdata
(
name
string
)
[]
byte
{
return
defaultManager
.
Getdata
(
name
)
}
// NGettext attempt to translate a text string into the user's native language,
// by looking up the appropriate plural form of the translation in a message
// catalog.
//
// It use the caller's function name as the msgctxt.
//
// Examples:
// func Foo() {
// msg := gettext.NGettext("%d people", "%d peoples", 2)
// }
func
NGettext
(
msgid
,
msgidPlural
string
,
n
int
)
string
{
return
PNGettext
(
callerName
(
2
),
msgid
,
msgidPlural
,
n
)
}
// PGettext attempt to translate a text string into the user's native language,
// by looking up the translation in a message catalog.
//
// Examples:
// func Foo() {
// msg := gettext.PGettext("gettext-go.example", "Hello") // msgctxt is "gettext-go.example"
// }
func
PGettext
(
msgctxt
,
msgid
string
)
string
{
return
PNGettext
(
msgctxt
,
msgid
,
""
,
0
)
}
// PNGettext attempt to translate a text string into the user's native language,
// by looking up the appropriate plural form of the translation in a message
// catalog.
//
// Examples:
// func Foo() {
// msg := gettext.PNGettext("gettext-go.example", "%d people", "%d peoples", 2)
// }
func
PNGettext
(
msgctxt
,
msgid
,
msgidPlural
string
,
n
int
)
string
{
return
defaultManager
.
PNGettext
(
msgctxt
,
msgid
,
msgidPlural
,
n
)
}
// DGettext like Gettext(), but looking up the message in the specified domain.
//
// Examples:
// func Foo() {
// msg := gettext.DGettext("poedit", "Hello")
// }
func
DGettext
(
domain
,
msgid
string
)
string
{
return
DPGettext
(
domain
,
callerName
(
2
),
msgid
)
}
// DNGettext like NGettext(), but looking up the message in the specified domain.
//
// Examples:
// func Foo() {
// msg := gettext.PNGettext("poedit", "gettext-go.example", "%d people", "%d peoples", 2)
// }
func
DNGettext
(
domain
,
msgid
,
msgidPlural
string
,
n
int
)
string
{
return
DPNGettext
(
domain
,
callerName
(
2
),
msgid
,
msgidPlural
,
n
)
}
// DPGettext like PGettext(), but looking up the message in the specified domain.
//
// Examples:
// func Foo() {
// msg := gettext.DPGettext("poedit", "gettext-go.example", "Hello")
// }
func
DPGettext
(
domain
,
msgctxt
,
msgid
string
)
string
{
return
DPNGettext
(
domain
,
msgctxt
,
msgid
,
""
,
0
)
}
// DPNGettext like PNGettext(), but looking up the message in the specified domain.
//
// Examples:
// func Foo() {
// msg := gettext.DPNGettext("poedit", "gettext-go.example", "%d people", "%d peoples", 2)
// }
func
DPNGettext
(
domain
,
msgctxt
,
msgid
,
msgidPlural
string
,
n
int
)
string
{
return
defaultManager
.
DPNGettext
(
domain
,
msgctxt
,
msgid
,
msgidPlural
,
n
)
}
// DGetdata like Getdata(), but looking up the resource in the specified domain.
//
// Examples:
// func Foo() {
// msg := gettext.DGetdata("hello", "poems.txt")
// }
func
DGetdata
(
domain
,
name
string
)
[]
byte
{
return
defaultManager
.
DGetdata
(
domain
,
name
)
}
vendor/github.com/chai2010/gettext-go/gettext/hello.go
0 → 100644
View file @
6dd760d3
// Copyright 2013 <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.
// +build ignore
package
main
import
(
"fmt"
"github.com/chai2010/gettext-go"
)
func
main
()
{
gettext
.
SetLocale
(
"zh_CN"
)
gettext
.
BindTextdomain
(
"hello"
,
"../examples/local"
,
nil
)
gettext
.
Textdomain
(
"hello"
)
fmt
.
Println
(
gettext
.
Gettext
(
"Hello, world!"
))
// Output: 你好, 世界!
}
vendor/github.com/chai2010/gettext-go/gettext/local.go
0 → 100644
View file @
6dd760d3
// 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
gettext
import
(
"os"
"strings"
)
func
getDefaultLocale
()
string
{
if
v
:=
os
.
Getenv
(
"LC_MESSAGES"
);
v
!=
""
{
return
simplifiedLocale
(
v
)
}
if
v
:=
os
.
Getenv
(
"LANG"
);
v
!=
""
{
return
simplifiedLocale
(
v
)
}
return
"default"
}
func
simplifiedLocale
(
lang
string
)
string
{
// en_US/en_US.UTF-8/zh_CN/zh_TW/el_GR@euro/...
if
idx
:=
strings
.
Index
(
lang
,
":"
);
idx
!=
-
1
{
lang
=
lang
[
:
idx
]
}
if
idx
:=
strings
.
Index
(
lang
,
"@"
);
idx
!=
-
1
{
lang
=
lang
[
:
idx
]
}
if
idx
:=
strings
.
Index
(
lang
,
"."
);
idx
!=
-
1
{
lang
=
lang
[
:
idx
]
}
return
strings
.
TrimSpace
(
lang
)
}
vendor/github.com/chai2010/gettext-go/gettext/mo/doc.go
0 → 100644
View file @
6dd760d3
// 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/gettext/mo"
)
func main() {
moFile, err := mo.Load("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
vendor/github.com/chai2010/gettext-go/gettext/mo/encoder.go
0 → 100644
View file @
6dd760d3
// 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
.
Sort
(
byMessages
(
msgList
))
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
}
type
byMessages
[]
Message
func
(
d
byMessages
)
Len
()
int
{
return
len
(
d
)
}
func
(
d
byMessages
)
Less
(
i
,
j
int
)
bool
{
if
a
,
b
:=
d
[
i
]
.
MsgContext
,
d
[
j
]
.
MsgContext
;
a
!=
b
{
return
a
<
b
}
if
a
,
b
:=
d
[
i
]
.
MsgId
,
d
[
j
]
.
MsgId
;
a
!=
b
{
return
a
<
b
}
if
a
,
b
:=
d
[
i
]
.
MsgIdPlural
,
d
[
j
]
.
MsgIdPlural
;
a
!=
b
{
return
a
<
b
}
return
false
}
func
(
d
byMessages
)
Swap
(
i
,
j
int
)
{
d
[
i
],
d
[
j
]
=
d
[
j
],
d
[
i
]
}
vendor/github.com/chai2010/gettext-go/gettext/mo/file.go
0 → 100644
View file @
6dd760d3
// 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 a named mo file.
func
Load
(
name
string
)
(
*
File
,
error
)
{
data
,
err
:=
ioutil
.
ReadFile
(
name
)
if
err
!=
nil
{
return
nil
,
err
}
return
LoadData
(
data
)
}
// LoadData loads mo file format 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
()
}
vendor/github.com/chai2010/gettext-go/gettext/mo/header.go
0 → 100644
View file @
6dd760d3
// 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
()
}
vendor/github.com/chai2010/gettext-go/gettext/mo/message.go
0 → 100644
View file @
6dd760d3
// 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
()
}
vendor/github.com/chai2010/gettext-go/gettext/mo/util.go
0 → 100644
View file @
6dd760d3
// 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
()
}
vendor/github.com/chai2010/gettext-go/gettext/plural/doc.go
0 → 100644
View file @
6dd760d3
// 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 plural provides standard plural formulas.
Examples:
import (
"code.google.com/p/gettext-go/gettext/plural"
)
func main() {
enFormula := plural.Formula("en_US")
xxFormula := plural.Formula("zh_CN")
fmt.Printf("%s: %d\n", "en", enFormula(0))
fmt.Printf("%s: %d\n", "en", enFormula(1))
fmt.Printf("%s: %d\n", "en", enFormula(2))
fmt.Printf("%s: %d\n", "??", xxFormula(0))
fmt.Printf("%s: %d\n", "??", xxFormula(1))
fmt.Printf("%s: %d\n", "??", xxFormula(2))
fmt.Printf("%s: %d\n", "??", xxFormula(9))
// Output:
// en: 0
// en: 0
// en: 1
// ??: 0
// ??: 0
// ??: 1
// ??: 8
}
See http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html
*/
package
plural
vendor/github.com/chai2010/gettext-go/gettext/plural/formula.go
0 → 100644
View file @
6dd760d3
// 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
plural
import
(
"strings"
)
// Formula provides the language's standard plural formula.
func
Formula
(
lang
string
)
func
(
n
int
)
int
{
if
idx
:=
index
(
lang
);
idx
!=
-
1
{
return
formulaTable
[
fmtForms
(
FormsTable
[
idx
]
.
Value
)]
}
if
idx
:=
index
(
"??"
);
idx
!=
-
1
{
return
formulaTable
[
fmtForms
(
FormsTable
[
idx
]
.
Value
)]
}
return
func
(
n
int
)
int
{
return
n
}
}
func
index
(
lang
string
)
int
{
for
i
:=
0
;
i
<
len
(
FormsTable
);
i
++
{
if
strings
.
HasPrefix
(
lang
,
FormsTable
[
i
]
.
Lang
)
{
return
i
}
}
return
-
1
}
func
fmtForms
(
forms
string
)
string
{
forms
=
strings
.
TrimSpace
(
forms
)
forms
=
strings
.
Replace
(
forms
,
" "
,
""
,
-
1
)
return
forms
}
var
formulaTable
=
map
[
string
]
func
(
n
int
)
int
{
fmtForms
(
"nplurals=n; plural=n-1;"
)
:
func
(
n
int
)
int
{
if
n
>
0
{
return
n
-
1
}
return
0
},
fmtForms
(
"nplurals=1; plural=0;"
)
:
func
(
n
int
)
int
{
return
0
},
fmtForms
(
"nplurals=2; plural=(n != 1);"
)
:
func
(
n
int
)
int
{
if
n
<=
1
{
return
0
}
return
1
},
fmtForms
(
"nplurals=2; plural=(n > 1);"
)
:
func
(
n
int
)
int
{
if
n
<=
1
{
return
0
}
return
1
},
fmtForms
(
"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);"
)
:
func
(
n
int
)
int
{
if
n
%
10
==
1
&&
n
%
100
!=
11
{
return
0
}
if
n
!=
0
{
return
1
}
return
2
},
fmtForms
(
"nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2;"
)
:
func
(
n
int
)
int
{
if
n
==
1
{
return
0
}
if
n
==
2
{
return
1
}
return
2
},
fmtForms
(
"nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2;"
)
:
func
(
n
int
)
int
{
if
n
==
1
{
return
0
}
if
n
==
0
||
(
n
%
100
>
0
&&
n
%
100
<
20
)
{
return
1
}
return
2
},
fmtForms
(
"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);"
)
:
func
(
n
int
)
int
{
if
n
%
10
==
1
&&
n
%
100
!=
11
{
return
0
}
if
n
%
10
>=
2
&&
(
n
%
100
<
10
||
n
%
100
>=
20
)
{
return
1
}
return
2
},
fmtForms
(
"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
)
:
func
(
n
int
)
int
{
if
n
%
10
==
1
&&
n
%
100
!=
11
{
return
0
}
if
n
%
10
>=
2
&&
n
%
10
<=
4
&&
(
n
%
100
<
10
||
n
%
100
>=
20
)
{
return
1
}
return
2
},
fmtForms
(
"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
)
:
func
(
n
int
)
int
{
if
n
%
10
==
1
&&
n
%
100
!=
11
{
return
0
}
if
n
%
10
>=
2
&&
n
%
10
<=
4
&&
(
n
%
100
<
10
||
n
%
100
>=
20
)
{
return
1
}
return
2
},
fmtForms
(
"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
)
:
func
(
n
int
)
int
{
if
n
%
10
==
1
&&
n
%
100
!=
11
{
return
0
}
if
n
%
10
>=
2
&&
n
%
10
<=
4
&&
(
n
%
100
<
10
||
n
%
100
>=
20
)
{
return
1
}
return
2
},
fmtForms
(
"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
)
:
func
(
n
int
)
int
{
if
n
%
10
==
1
&&
n
%
100
!=
11
{
return
0
}
if
n
%
10
>=
2
&&
n
%
10
<=
4
&&
(
n
%
100
<
10
||
n
%
100
>=
20
)
{
return
1
}
return
2
},
fmtForms
(
"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
)
:
func
(
n
int
)
int
{
if
n
%
10
==
1
&&
n
%
100
!=
11
{
return
0
}
if
n
%
10
>=
2
&&
n
%
10
<=
4
&&
(
n
%
100
<
10
||
n
%
100
>=
20
)
{
return
1
}
return
2
},
fmtForms
(
"nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;"
)
:
func
(
n
int
)
int
{
if
n
==
1
{
return
0
}
if
n
>=
2
&&
n
<=
4
{
return
1
}
return
2
},
fmtForms
(
"nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;"
)
:
func
(
n
int
)
int
{
if
n
==
1
{
return
0
}
if
n
>=
2
&&
n
<=
4
{
return
1
}
return
2
},
fmtForms
(
"nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
)
:
func
(
n
int
)
int
{
if
n
==
1
{
return
0
}
if
n
%
10
>=
2
&&
n
%
10
<=
4
&&
(
n
%
100
<
10
||
n
%
100
>=
20
)
{
return
1
}
return
2
},
fmtForms
(
"nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);"
)
:
func
(
n
int
)
int
{
if
n
%
100
==
1
{
return
0
}
if
n
%
100
==
2
{
return
1
}
if
n
%
100
==
3
||
n
%
100
==
4
{
return
2
}
return
3
},
}
vendor/github.com/chai2010/gettext-go/gettext/plural/table.go
0 → 100644
View file @
6dd760d3
// 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
plural
// FormsTable are standard hard-coded plural rules.
// The application developers and the translators need to understand them.
//
// See GNU's gettext library source code: gettext/gettext-tools/src/plural-table.c
var
FormsTable
=
[]
struct
{
Lang
string
Language
string
Value
string
}{
{
"??"
,
"Unknown"
,
"nplurals=1; plural=0;"
},
{
"ja"
,
"Japanese"
,
"nplurals=1; plural=0;"
},
{
"vi"
,
"Vietnamese"
,
"nplurals=1; plural=0;"
},
{
"ko"
,
"Korean"
,
"nplurals=1; plural=0;"
},
{
"en"
,
"English"
,
"nplurals=2; plural=(n != 1);"
},
{
"de"
,
"German"
,
"nplurals=2; plural=(n != 1);"
},
{
"nl"
,
"Dutch"
,
"nplurals=2; plural=(n != 1);"
},
{
"sv"
,
"Swedish"
,
"nplurals=2; plural=(n != 1);"
},
{
"da"
,
"Danish"
,
"nplurals=2; plural=(n != 1);"
},
{
"no"
,
"Norwegian"
,
"nplurals=2; plural=(n != 1);"
},
{
"nb"
,
"Norwegian Bokmal"
,
"nplurals=2; plural=(n != 1);"
},
{
"nn"
,
"Norwegian Nynorsk"
,
"nplurals=2; plural=(n != 1);"
},
{
"fo"
,
"Faroese"
,
"nplurals=2; plural=(n != 1);"
},
{
"es"
,
"Spanish"
,
"nplurals=2; plural=(n != 1);"
},
{
"pt"
,
"Portuguese"
,
"nplurals=2; plural=(n != 1);"
},
{
"it"
,
"Italian"
,
"nplurals=2; plural=(n != 1);"
},
{
"bg"
,
"Bulgarian"
,
"nplurals=2; plural=(n != 1);"
},
{
"el"
,
"Greek"
,
"nplurals=2; plural=(n != 1);"
},
{
"fi"
,
"Finnish"
,
"nplurals=2; plural=(n != 1);"
},
{
"et"
,
"Estonian"
,
"nplurals=2; plural=(n != 1);"
},
{
"he"
,
"Hebrew"
,
"nplurals=2; plural=(n != 1);"
},
{
"eo"
,
"Esperanto"
,
"nplurals=2; plural=(n != 1);"
},
{
"hu"
,
"Hungarian"
,
"nplurals=2; plural=(n != 1);"
},
{
"tr"
,
"Turkish"
,
"nplurals=2; plural=(n != 1);"
},
{
"pt_BR"
,
"Brazilian"
,
"nplurals=2; plural=(n > 1);"
},
{
"fr"
,
"French"
,
"nplurals=2; plural=(n > 1);"
},
{
"lv"
,
"Latvian"
,
"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);"
},
{
"ga"
,
"Irish"
,
"nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2;"
},
{
"ro"
,
"Romanian"
,
"nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2;"
},
{
"lt"
,
"Lithuanian"
,
"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);"
},
{
"ru"
,
"Russian"
,
"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
},
{
"uk"
,
"Ukrainian"
,
"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
},
{
"be"
,
"Belarusian"
,
"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
},
{
"sr"
,
"Serbian"
,
"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
},
{
"hr"
,
"Croatian"
,
"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
},
{
"cs"
,
"Czech"
,
"nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;"
},
{
"sk"
,
"Slovak"
,
"nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;"
},
{
"pl"
,
"Polish"
,
"nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
},
{
"sl"
,
"Slovenian"
,
"nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);"
},
}
vendor/github.com/chai2010/gettext-go/gettext/po/comment.go
0 → 100644
View file @
6dd760d3
// 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
po
import
(
"bytes"
"fmt"
"io"
"strconv"
"strings"
)
// Comment represents every message's comments.
type
Comment
struct
{
StartLine
int
// comment start line
TranslatorComment
string
// # translator-comments // TrimSpace
ExtractedComment
string
// #. extracted-comments
ReferenceFile
[]
string
// #: src/msgcmp.c:338 src/po-lex.c:699
ReferenceLine
[]
int
// #: src/msgcmp.c:338 src/po-lex.c:699
Flags
[]
string
// #, fuzzy,c-format,range:0..10
PrevMsgContext
string
// #| msgctxt previous-context
PrevMsgId
string
// #| msgid previous-untranslated-string
}
func
(
p
*
Comment
)
less
(
q
*
Comment
)
bool
{
if
p
.
StartLine
!=
0
||
q
.
StartLine
!=
0
{
return
p
.
StartLine
<
q
.
StartLine
}
if
a
,
b
:=
len
(
p
.
ReferenceFile
),
len
(
q
.
ReferenceFile
);
a
!=
b
{
return
a
<
b
}
for
i
:=
0
;
i
<
len
(
p
.
ReferenceFile
);
i
++
{
if
a
,
b
:=
p
.
ReferenceFile
[
i
],
q
.
ReferenceFile
[
i
];
a
!=
b
{
return
a
<
b
}
if
a
,
b
:=
p
.
ReferenceLine
[
i
],
q
.
ReferenceLine
[
i
];
a
!=
b
{
return
a
<
b
}
}
return
false
}
func
(
p
*
Comment
)
readPoComment
(
r
*
lineReader
)
(
err
error
)
{
*
p
=
Comment
{}
if
err
=
r
.
skipBlankLine
();
err
!=
nil
{
return
err
}
defer
func
(
oldPos
int
)
{
newPos
:=
r
.
currentPos
()
if
newPos
!=
oldPos
&&
err
==
io
.
EOF
{
err
=
nil
}
}(
r
.
currentPos
())
p
.
StartLine
=
r
.
currentPos
()
+
1
for
{
var
s
string
if
s
,
_
,
err
=
r
.
currentLine
();
err
!=
nil
{
return
}
if
len
(
s
)
==
0
||
s
[
0
]
!=
'#'
{
return
}
if
err
=
p
.
readTranslatorComment
(
r
);
err
!=
nil
{
return
}
if
err
=
p
.
readExtractedComment
(
r
);
err
!=
nil
{
return
}
if
err
=
p
.
readReferenceComment
(
r
);
err
!=
nil
{
return
}
if
err
=
p
.
readFlagsComment
(
r
);
err
!=
nil
{
return
}
if
err
=
p
.
readPrevMsgContext
(
r
);
err
!=
nil
{
return
}
if
err
=
p
.
readPrevMsgId
(
r
);
err
!=
nil
{
return
}
}
}
func
(
p
*
Comment
)
readTranslatorComment
(
r
*
lineReader
)
(
err
error
)
{
const
prefix
=
"# "
// .,:|
for
{
var
s
string
if
s
,
_
,
err
=
r
.
readLine
();
err
!=
nil
{
return
err
}
if
len
(
s
)
<
1
||
s
[
0
]
!=
'#'
{
r
.
unreadLine
()
return
nil
}
if
len
(
s
)
>=
2
{
switch
s
[
1
]
{
case
'.'
,
','
,
':'
,
'|'
:
r
.
unreadLine
()
return
nil
}
}
if
p
.
TranslatorComment
!=
""
{
p
.
TranslatorComment
+=
"
\n
"
}
p
.
TranslatorComment
+=
strings
.
TrimSpace
(
s
[
1
:
])
}
}
func
(
p
*
Comment
)
readExtractedComment
(
r
*
lineReader
)
(
err
error
)
{
const
prefix
=
"#."
for
{
var
s
string
if
s
,
_
,
err
=
r
.
readLine
();
err
!=
nil
{
return
err
}
if
len
(
s
)
<
len
(
prefix
)
||
s
[
:
len
(
prefix
)]
!=
prefix
{
r
.
unreadLine
()
return
nil
}
if
p
.
ExtractedComment
!=
""
{
p
.
ExtractedComment
+=
"
\n
"
}
p
.
ExtractedComment
+=
strings
.
TrimSpace
(
s
[
len
(
prefix
)
:
])
}
}
func
(
p
*
Comment
)
readReferenceComment
(
r
*
lineReader
)
(
err
error
)
{
const
prefix
=
"#:"
for
{
var
s
string
if
s
,
_
,
err
=
r
.
readLine
();
err
!=
nil
{
return
err
}
if
len
(
s
)
<
len
(
prefix
)
||
s
[
:
len
(
prefix
)]
!=
prefix
{
r
.
unreadLine
()
return
nil
}
ss
:=
strings
.
Split
(
strings
.
TrimSpace
(
s
[
len
(
prefix
)
:
]),
" "
)
for
i
:=
0
;
i
<
len
(
ss
);
i
++
{
idx
:=
strings
.
Index
(
ss
[
i
],
":"
)
if
idx
<=
0
{
continue
}
name
:=
strings
.
TrimSpace
(
ss
[
i
][
:
idx
])
line
,
_
:=
strconv
.
Atoi
(
strings
.
TrimSpace
(
ss
[
i
][
idx
+
1
:
]))
p
.
ReferenceFile
=
append
(
p
.
ReferenceFile
,
name
)
p
.
ReferenceLine
=
append
(
p
.
ReferenceLine
,
line
)
}
}
}
func
(
p
*
Comment
)
readFlagsComment
(
r
*
lineReader
)
(
err
error
)
{
const
prefix
=
"#,"
for
{
var
s
string
if
s
,
_
,
err
=
r
.
readLine
();
err
!=
nil
{
return
err
}
if
len
(
s
)
<
len
(
prefix
)
||
s
[
:
len
(
prefix
)]
!=
prefix
{
r
.
unreadLine
()
return
nil
}
ss
:=
strings
.
Split
(
strings
.
TrimSpace
(
s
[
len
(
prefix
)
:
]),
","
)
for
i
:=
0
;
i
<
len
(
ss
);
i
++
{
p
.
Flags
=
append
(
p
.
Flags
,
strings
.
TrimSpace
(
ss
[
i
]))
}
}
}
func
(
p
*
Comment
)
readPrevMsgContext
(
r
*
lineReader
)
(
err
error
)
{
var
s
string
if
s
,
_
,
err
=
r
.
currentLine
();
err
!=
nil
{
return
}
if
!
rePrevMsgContextComments
.
MatchString
(
s
)
{
return
}
p
.
PrevMsgContext
,
err
=
p
.
readString
(
r
)
return
}
func
(
p
*
Comment
)
readPrevMsgId
(
r
*
lineReader
)
(
err
error
)
{
var
s
string
if
s
,
_
,
err
=
r
.
currentLine
();
err
!=
nil
{
return
}
if
!
rePrevMsgIdComments
.
MatchString
(
s
)
{
return
}
p
.
PrevMsgId
,
err
=
p
.
readString
(
r
)
return
}
func
(
p
*
Comment
)
readString
(
r
*
lineReader
)
(
msg
string
,
err
error
)
{
var
s
string
if
s
,
_
,
err
=
r
.
readLine
();
err
!=
nil
{
return
}
msg
+=
decodePoString
(
s
)
for
{
if
s
,
_
,
err
=
r
.
readLine
();
err
!=
nil
{
return
}
if
!
reStringLineComments
.
MatchString
(
s
)
{
r
.
unreadLine
()
break
}
msg
+=
decodePoString
(
s
)
}
return
}
// GetFuzzy gets the fuzzy flag.
func
(
p
*
Comment
)
GetFuzzy
()
bool
{
for
_
,
s
:=
range
p
.
Flags
{
if
s
==
"fuzzy"
{
return
true
}
}
return
false
}
// SetFuzzy sets the fuzzy flag.
func
(
p
*
Comment
)
SetFuzzy
(
fuzzy
bool
)
{
//
}
// String returns the po format comment string.
func
(
p
Comment
)
String
()
string
{
var
buf
bytes
.
Buffer
if
p
.
TranslatorComment
!=
""
{
ss
:=
strings
.
Split
(
p
.
TranslatorComment
,
"
\n
"
)
for
i
:=
0
;
i
<
len
(
ss
);
i
++
{
fmt
.
Fprintf
(
&
buf
,
"# %s
\n
"
,
ss
[
i
])
}
}
if
p
.
ExtractedComment
!=
""
{
ss
:=
strings
.
Split
(
p
.
ExtractedComment
,
"
\n
"
)
for
i
:=
0
;
i
<
len
(
ss
);
i
++
{
fmt
.
Fprintf
(
&
buf
,
"#. %s
\n
"
,
ss
[
i
])
}
}
if
a
,
b
:=
len
(
p
.
ReferenceFile
),
len
(
p
.
ReferenceLine
);
a
!=
0
&&
a
==
b
{
fmt
.
Fprintf
(
&
buf
,
"#:"
)
for
i
:=
0
;
i
<
len
(
p
.
ReferenceFile
);
i
++
{
fmt
.
Fprintf
(
&
buf
,
" %s:%d"
,
p
.
ReferenceFile
[
i
],
p
.
ReferenceLine
[
i
])
}
fmt
.
Fprintf
(
&
buf
,
"
\n
"
)
}
if
len
(
p
.
Flags
)
!=
0
{
fmt
.
Fprintf
(
&
buf
,
"#, %s"
,
p
.
Flags
[
0
])
for
i
:=
1
;
i
<
len
(
p
.
Flags
);
i
++
{
fmt
.
Fprintf
(
&
buf
,
", %s"
,
p
.
Flags
[
i
])
}
fmt
.
Fprintf
(
&
buf
,
"
\n
"
)
}
if
p
.
PrevMsgContext
!=
""
{
s
:=
encodeCommentPoString
(
p
.
PrevMsgContext
)
fmt
.
Fprintf
(
&
buf
,
"#| msgctxt %s
\n
"
,
s
)
}
if
p
.
PrevMsgId
!=
""
{
s
:=
encodeCommentPoString
(
p
.
PrevMsgId
)
fmt
.
Fprintf
(
&
buf
,
"#| msgid %s
\n
"
,
s
)
}
return
buf
.
String
()
}
vendor/github.com/chai2010/gettext-go/gettext/po/doc.go
0 → 100644
View file @
6dd760d3
// 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 po provides support for reading and writing GNU PO file.
Examples:
import (
"github.com/chai2010/gettext-go/gettext/po"
)
func main() {
poFile, err := po.Load("test.po")
if err != nil {
log.Fatal(err)
}
fmt.Printf("%v", poFile)
}
The GNU PO file specification is at
http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html.
*/
package
po
vendor/github.com/chai2010/gettext-go/gettext/po/file.go
0 → 100644
View file @
6dd760d3
// 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
po
import
(
"bytes"
"fmt"
"io"
"io/ioutil"
"sort"
)
// File represents an PO File.
//
// See http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html
type
File
struct
{
MimeHeader
Header
Messages
[]
Message
}
// Load loads a named po file.
func
Load
(
name
string
)
(
*
File
,
error
)
{
data
,
err
:=
ioutil
.
ReadFile
(
name
)
if
err
!=
nil
{
return
nil
,
err
}
return
LoadData
(
data
)
}
// LoadData loads po file format data.
func
LoadData
(
data
[]
byte
)
(
*
File
,
error
)
{
r
:=
newLineReader
(
string
(
data
))
var
file
File
for
{
var
msg
Message
if
err
:=
msg
.
readPoEntry
(
r
);
err
!=
nil
{
if
err
==
io
.
EOF
{
return
&
file
,
nil
}
return
nil
,
err
}
if
msg
.
MsgId
==
""
{
file
.
MimeHeader
.
parseHeader
(
&
msg
)
continue
}
file
.
Messages
=
append
(
file
.
Messages
,
msg
)
}
}
// Save saves a po file.
func
(
f
*
File
)
Save
(
name
string
)
error
{
return
ioutil
.
WriteFile
(
name
,
[]
byte
(
f
.
String
()),
0666
)
}
// Save returns a po file format data.
func
(
f
*
File
)
Data
()
[]
byte
{
// sort the massge as ReferenceFile/ReferenceLine field
var
messages
[]
Message
messages
=
append
(
messages
,
f
.
Messages
...
)
sort
.
Sort
(
byMessages
(
messages
))
var
buf
bytes
.
Buffer
fmt
.
Fprintf
(
&
buf
,
"%s
\n
"
,
f
.
MimeHeader
.
String
())
for
i
:=
0
;
i
<
len
(
messages
);
i
++
{
fmt
.
Fprintf
(
&
buf
,
"%s
\n
"
,
messages
[
i
]
.
String
())
}
return
buf
.
Bytes
()
}
// String returns the po format file string.
func
(
f
*
File
)
String
()
string
{
return
string
(
f
.
Data
())
}
vendor/github.com/chai2010/gettext-go/gettext/po/header.go
0 → 100644
View file @
6dd760d3
// 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
po
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
{
Comment
// Header Comments
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
)
parseHeader
(
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
}
}
p
.
Comment
=
msg
.
Comment
}
// String returns the po format header string.
func
(
p
Header
)
String
()
string
{
var
buf
bytes
.
Buffer
fmt
.
Fprintf
(
&
buf
,
"%s"
,
p
.
Comment
.
String
())
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
()
}
vendor/github.com/chai2010/gettext-go/gettext/po/line_reader.go
0 → 100644
View file @
6dd760d3
// 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
po
import
(
"io"
"strings"
)
type
lineReader
struct
{
lines
[]
string
pos
int
}
func
newLineReader
(
data
string
)
*
lineReader
{
data
=
strings
.
Replace
(
data
,
"
\r
"
,
""
,
-
1
)
lines
:=
strings
.
Split
(
data
,
"
\n
"
)
return
&
lineReader
{
lines
:
lines
}
}
func
(
r
*
lineReader
)
skipBlankLine
()
error
{
for
;
r
.
pos
<
len
(
r
.
lines
);
r
.
pos
++
{
if
strings
.
TrimSpace
(
r
.
lines
[
r
.
pos
])
!=
""
{
break
}
}
if
r
.
pos
>=
len
(
r
.
lines
)
{
return
io
.
EOF
}
return
nil
}
func
(
r
*
lineReader
)
currentPos
()
int
{
return
r
.
pos
}
func
(
r
*
lineReader
)
currentLine
()
(
s
string
,
pos
int
,
err
error
)
{
if
r
.
pos
>=
len
(
r
.
lines
)
{
err
=
io
.
EOF
return
}
s
,
pos
=
r
.
lines
[
r
.
pos
],
r
.
pos
return
}
func
(
r
*
lineReader
)
readLine
()
(
s
string
,
pos
int
,
err
error
)
{
if
r
.
pos
>=
len
(
r
.
lines
)
{
err
=
io
.
EOF
return
}
s
,
pos
=
r
.
lines
[
r
.
pos
],
r
.
pos
r
.
pos
++
return
}
func
(
r
*
lineReader
)
unreadLine
()
{
if
r
.
pos
>=
0
{
r
.
pos
--
}
}
vendor/github.com/chai2010/gettext-go/gettext/po/message.go
0 → 100644
View file @
6dd760d3
// 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
po
import
(
"bytes"
"fmt"
"io"
"strconv"
"strings"
)
// A PO 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/PO-Files.html
type
Message
struct
{
Comment
// Coments
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
}
type
byMessages
[]
Message
func
(
d
byMessages
)
Len
()
int
{
return
len
(
d
)
}
func
(
d
byMessages
)
Less
(
i
,
j
int
)
bool
{
if
d
[
i
]
.
Comment
.
less
(
&
d
[
j
]
.
Comment
)
{
return
true
}
if
a
,
b
:=
d
[
i
]
.
MsgContext
,
d
[
j
]
.
MsgContext
;
a
!=
b
{
return
a
<
b
}
if
a
,
b
:=
d
[
i
]
.
MsgId
,
d
[
j
]
.
MsgId
;
a
!=
b
{
return
a
<
b
}
if
a
,
b
:=
d
[
i
]
.
MsgIdPlural
,
d
[
j
]
.
MsgIdPlural
;
a
!=
b
{
return
a
<
b
}
return
false
}
func
(
d
byMessages
)
Swap
(
i
,
j
int
)
{
d
[
i
],
d
[
j
]
=
d
[
j
],
d
[
i
]
}
func
(
p
*
Message
)
readPoEntry
(
r
*
lineReader
)
(
err
error
)
{
*
p
=
Message
{}
if
err
=
r
.
skipBlankLine
();
err
!=
nil
{
return
}
defer
func
(
oldPos
int
)
{
newPos
:=
r
.
currentPos
()
if
newPos
!=
oldPos
&&
err
==
io
.
EOF
{
err
=
nil
}
}(
r
.
currentPos
())
if
err
=
p
.
Comment
.
readPoComment
(
r
);
err
!=
nil
{
return
}
for
{
var
s
string
if
s
,
_
,
err
=
r
.
currentLine
();
err
!=
nil
{
return
}
if
p
.
isInvalidLine
(
s
)
{
err
=
fmt
.
Errorf
(
"gettext: line %d, %v"
,
r
.
currentPos
(),
"invalid line"
)
return
}
if
reComment
.
MatchString
(
s
)
||
reBlankLine
.
MatchString
(
s
)
{
return
}
if
err
=
p
.
readMsgContext
(
r
);
err
!=
nil
{
return
}
if
err
=
p
.
readMsgId
(
r
);
err
!=
nil
{
return
}
if
err
=
p
.
readMsgIdPlural
(
r
);
err
!=
nil
{
return
}
if
err
=
p
.
readMsgStrOrPlural
(
r
);
err
!=
nil
{
return
}
}
}
func
(
p
*
Message
)
readMsgContext
(
r
*
lineReader
)
(
err
error
)
{
var
s
string
if
s
,
_
,
err
=
r
.
currentLine
();
err
!=
nil
{
return
}
if
!
reMsgContext
.
MatchString
(
s
)
{
return
}
p
.
MsgContext
,
err
=
p
.
readString
(
r
)
return
}
func
(
p
*
Message
)
readMsgId
(
r
*
lineReader
)
(
err
error
)
{
var
s
string
if
s
,
_
,
err
=
r
.
currentLine
();
err
!=
nil
{
return
}
if
!
reMsgId
.
MatchString
(
s
)
{
return
}
p
.
MsgId
,
err
=
p
.
readString
(
r
)
return
}
func
(
p
*
Message
)
readMsgIdPlural
(
r
*
lineReader
)
(
err
error
)
{
var
s
string
if
s
,
_
,
err
=
r
.
currentLine
();
err
!=
nil
{
return
}
if
!
reMsgIdPlural
.
MatchString
(
s
)
{
return
}
p
.
MsgIdPlural
,
err
=
p
.
readString
(
r
)
return
nil
}
func
(
p
*
Message
)
readMsgStrOrPlural
(
r
*
lineReader
)
(
err
error
)
{
var
s
string
if
s
,
_
,
err
=
r
.
currentLine
();
err
!=
nil
{
return
}
if
!
reMsgStr
.
MatchString
(
s
)
&&
!
reMsgStrPlural
.
MatchString
(
s
)
{
return
}
if
reMsgStrPlural
.
MatchString
(
s
)
{
left
,
right
:=
strings
.
Index
(
s
,
`[`
),
strings
.
LastIndex
(
s
,
`]`
)
idx
,
_
:=
strconv
.
Atoi
(
s
[
left
+
1
:
right
])
s
,
err
=
p
.
readString
(
r
)
if
n
:=
len
(
p
.
MsgStrPlural
);
(
idx
+
1
)
>
n
{
p
.
MsgStrPlural
=
append
(
p
.
MsgStrPlural
,
make
([]
string
,
(
idx
+
1
)
-
n
)
...
)
}
p
.
MsgStrPlural
[
idx
]
=
s
}
else
{
p
.
MsgStr
,
err
=
p
.
readString
(
r
)
}
return
nil
}
func
(
p
*
Message
)
readString
(
r
*
lineReader
)
(
msg
string
,
err
error
)
{
var
s
string
if
s
,
_
,
err
=
r
.
readLine
();
err
!=
nil
{
return
}
msg
+=
decodePoString
(
s
)
for
{
if
s
,
_
,
err
=
r
.
readLine
();
err
!=
nil
{
return
}
if
!
reStringLine
.
MatchString
(
s
)
{
r
.
unreadLine
()
break
}
msg
+=
decodePoString
(
s
)
}
return
}
// String returns the po format entry string.
func
(
p
Message
)
String
()
string
{
var
buf
bytes
.
Buffer
fmt
.
Fprintf
(
&
buf
,
"%s"
,
p
.
Comment
.
String
())
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
()
}
vendor/github.com/chai2010/gettext-go/gettext/po/re.go
0 → 100644
View file @
6dd760d3
// 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
po
import
(
"regexp"
)
var
(
reComment
=
regexp
.
MustCompile
(
`^#`
)
// #
reExtractedComments
=
regexp
.
MustCompile
(
`^#\.`
)
// #.
reReferenceComments
=
regexp
.
MustCompile
(
`^#:`
)
// #:
reFlagsComments
=
regexp
.
MustCompile
(
`^#,`
)
// #, fuzzy,c-format
rePrevMsgContextComments
=
regexp
.
MustCompile
(
`^#\|\s+msgctxt`
)
// #| msgctxt
rePrevMsgIdComments
=
regexp
.
MustCompile
(
`^#\|\s+msgid`
)
// #| msgid
reStringLineComments
=
regexp
.
MustCompile
(
`^#\|\s+".*"\s*$`
)
// #| "message"
reMsgContext
=
regexp
.
MustCompile
(
`^msgctxt\s+".*"\s*$`
)
// msgctxt
reMsgId
=
regexp
.
MustCompile
(
`^msgid\s+".*"\s*$`
)
// msgid
reMsgIdPlural
=
regexp
.
MustCompile
(
`^msgid_plural\s+".*"\s*$`
)
// msgid_plural
reMsgStr
=
regexp
.
MustCompile
(
`^msgstr\s*".*"\s*$`
)
// msgstr
reMsgStrPlural
=
regexp
.
MustCompile
(
`^msgstr\s*(\[\d+\])\s*".*"\s*$`
)
// msgstr[0]
reStringLine
=
regexp
.
MustCompile
(
`^\s*".*"\s*$`
)
// "message"
reBlankLine
=
regexp
.
MustCompile
(
`^\s*$`
)
//
)
func
(
p
*
Message
)
isInvalidLine
(
s
string
)
bool
{
if
reComment
.
MatchString
(
s
)
{
return
false
}
if
reBlankLine
.
MatchString
(
s
)
{
return
false
}
if
reMsgContext
.
MatchString
(
s
)
{
return
false
}
if
reMsgId
.
MatchString
(
s
)
{
return
false
}
if
reMsgIdPlural
.
MatchString
(
s
)
{
return
false
}
if
reMsgStr
.
MatchString
(
s
)
{
return
false
}
if
reMsgStrPlural
.
MatchString
(
s
)
{
return
false
}
if
reStringLine
.
MatchString
(
s
)
{
return
false
}
return
true
}
vendor/github.com/chai2010/gettext-go/gettext/po/util.go
0 → 100644
View file @
6dd760d3
// 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
po
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
()
}
vendor/github.com/chai2010/gettext-go/gettext/tr.go
0 → 100644
View file @
6dd760d3
// 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
gettext
import
(
"github.com/chai2010/gettext-go/gettext/mo"
"github.com/chai2010/gettext-go/gettext/plural"
"github.com/chai2010/gettext-go/gettext/po"
)
var
nilTranslator
=
&
translator
{
MessageMap
:
make
(
map
[
string
]
mo
.
Message
),
PluralFormula
:
plural
.
Formula
(
"??"
),
}
type
translator
struct
{
MessageMap
map
[
string
]
mo
.
Message
PluralFormula
func
(
n
int
)
int
}
func
newMoTranslator
(
name
string
,
data
[]
byte
)
(
*
translator
,
error
)
{
var
(
f
*
mo
.
File
err
error
)
if
len
(
data
)
!=
0
{
f
,
err
=
mo
.
LoadData
(
data
)
}
else
{
f
,
err
=
mo
.
Load
(
name
)
}
if
err
!=
nil
{
return
nil
,
err
}
var
tr
=
&
translator
{
MessageMap
:
make
(
map
[
string
]
mo
.
Message
),
}
for
_
,
v
:=
range
f
.
Messages
{
tr
.
MessageMap
[
tr
.
makeMapKey
(
v
.
MsgContext
,
v
.
MsgId
)]
=
v
}
if
lang
:=
f
.
MimeHeader
.
Language
;
lang
!=
""
{
tr
.
PluralFormula
=
plural
.
Formula
(
lang
)
}
else
{
tr
.
PluralFormula
=
plural
.
Formula
(
"??"
)
}
return
tr
,
nil
}
func
newPoTranslator
(
name
string
,
data
[]
byte
)
(
*
translator
,
error
)
{
var
(
f
*
po
.
File
err
error
)
if
len
(
data
)
!=
0
{
f
,
err
=
po
.
LoadData
(
data
)
}
else
{
f
,
err
=
po
.
Load
(
name
)
}
if
err
!=
nil
{
return
nil
,
err
}
var
tr
=
&
translator
{
MessageMap
:
make
(
map
[
string
]
mo
.
Message
),
}
for
_
,
v
:=
range
f
.
Messages
{
tr
.
MessageMap
[
tr
.
makeMapKey
(
v
.
MsgContext
,
v
.
MsgId
)]
=
mo
.
Message
{
MsgContext
:
v
.
MsgContext
,
MsgId
:
v
.
MsgId
,
MsgIdPlural
:
v
.
MsgIdPlural
,
MsgStr
:
v
.
MsgStr
,
MsgStrPlural
:
v
.
MsgStrPlural
,
}
}
if
lang
:=
f
.
MimeHeader
.
Language
;
lang
!=
""
{
tr
.
PluralFormula
=
plural
.
Formula
(
lang
)
}
else
{
tr
.
PluralFormula
=
plural
.
Formula
(
"??"
)
}
return
tr
,
nil
}
func
(
p
*
translator
)
PGettext
(
msgctxt
,
msgid
string
)
string
{
return
p
.
PNGettext
(
msgctxt
,
msgid
,
""
,
0
)
}
func
(
p
*
translator
)
PNGettext
(
msgctxt
,
msgid
,
msgidPlural
string
,
n
int
)
string
{
n
=
p
.
PluralFormula
(
n
)
if
ss
:=
p
.
findMsgStrPlural
(
msgctxt
,
msgid
,
msgidPlural
);
len
(
ss
)
!=
0
{
if
n
>=
len
(
ss
)
{
n
=
len
(
ss
)
-
1
}
if
ss
[
n
]
!=
""
{
return
ss
[
n
]
}
}
if
msgidPlural
!=
""
&&
n
>
0
{
return
msgidPlural
}
return
msgid
}
func
(
p
*
translator
)
findMsgStrPlural
(
msgctxt
,
msgid
,
msgidPlural
string
)
[]
string
{
key
:=
p
.
makeMapKey
(
msgctxt
,
msgid
)
if
v
,
ok
:=
p
.
MessageMap
[
key
];
ok
{
if
len
(
v
.
MsgIdPlural
)
!=
0
{
if
len
(
v
.
MsgStrPlural
)
!=
0
{
return
v
.
MsgStrPlural
}
else
{
return
nil
}
}
else
{
if
len
(
v
.
MsgStr
)
!=
0
{
return
[]
string
{
v
.
MsgStr
}
}
else
{
return
nil
}
}
}
return
nil
}
func
(
p
*
translator
)
makeMapKey
(
msgctxt
,
msgid
string
)
string
{
if
msgctxt
!=
""
{
return
msgctxt
+
mo
.
EotSeparator
+
msgid
}
return
msgid
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment