forked from snapcore/snapd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
i18n.go
135 lines (112 loc) · 3.17 KB
/
i18n.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// -*- Mode: Go; indent-tabs-mode: t -*-
/*
* Copyright (C) 2014-2015 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package i18n
//go:generate update-pot
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/snapcore/go-gettext"
"github.com/snapcore/snapd/dirs"
"github.com/snapcore/snapd/osutil"
)
// TEXTDOMAIN is the message domain used by snappy; see dgettext(3)
// for more information.
var (
TEXTDOMAIN = "snappy"
locale gettext.Catalog
translations gettext.Translations
)
func init() {
bindTextDomain(TEXTDOMAIN, "/usr/share/locale")
setLocale("")
}
func langpackResolver(baseRoot string, locale string, domain string) string {
// first check for the real locale (e.g. de_DE)
// then try to simplify the locale (e.g. de_DE -> de)
locales := []string{locale, strings.SplitN(locale, "_", 2)[0]}
for _, locale := range locales {
r := filepath.Join(locale, "LC_MESSAGES", fmt.Sprintf("%s.mo", domain))
// look into the core snaps first for translations,
// then the main system
candidateDirs := []string{
filepath.Join(dirs.SnapMountDir, "/core/current/", baseRoot),
baseRoot,
}
for _, root := range candidateDirs {
// ubuntu uses /usr/lib/locale-langpack and patches the glibc gettext
// implementation
langpack := filepath.Join(root, "..", "locale-langpack", r)
if osutil.FileExists(langpack) {
return langpack
}
regular := filepath.Join(root, r)
if osutil.FileExists(regular) {
return regular
}
}
}
return ""
}
func bindTextDomain(domain, dir string) {
translations = gettext.NewTranslations(dir, domain, langpackResolver)
}
func setLocale(loc string) {
if loc == "" {
loc = localeFromEnv()
}
locale = translations.Locale(simplifyLocale(loc))
}
func simplifyLocale(loc string) string {
// de_DE.UTF-8, de_DE@euro all need to get simplified
loc = strings.Split(loc, "@")[0]
loc = strings.Split(loc, ".")[0]
return loc
}
func localeFromEnv() string {
loc := os.Getenv("LC_MESSAGES")
if loc == "" {
loc = os.Getenv("LANG")
}
return loc
}
// CurrentLocale returns the current locale without encoding or variants.
func CurrentLocale() string {
return simplifyLocale(localeFromEnv())
}
// G is the shorthand for Gettext
func G(msgid string) string {
return locale.Gettext(msgid)
}
// https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html
// (search for 1000)
func ngn(d int) uint32 {
const max = 1000000
if d < 0 {
d = -d
}
if d > max {
return uint32((d % max) + max)
}
return uint32(d)
}
// NG is the shorthand for NGettext
func NG(msgid string, msgidPlural string, n int) string {
return locale.NGettext(msgid, msgidPlural, ngn(n))
}