summaryrefslogtreecommitdiff
path: root/plugin/maxmind
diff options
context:
space:
mode:
authorLoyalsoldier <[email protected]>2026-01-22 11:37:11 +0800
committerLoyalsoldier <[email protected]>2026-01-22 11:37:11 +0800
commitac53325ec76e43fb981c694cb44badf9cbb07e8d (patch)
tree12bd44c19206cbdb06eab8acefc362fbf5dfdb7d /plugin/maxmind
parent77e5f4a2c24fb87f79e73c05729562138df8279e (diff)
Diffstat (limited to 'plugin/maxmind')
-rw-r--r--plugin/maxmind/common_out.go152
-rw-r--r--plugin/maxmind/maxmind_country_mmdb_in.go35
-rw-r--r--plugin/maxmind/maxmind_country_mmdb_out.go118
3 files changed, 202 insertions, 103 deletions
diff --git a/plugin/maxmind/common_out.go b/plugin/maxmind/common_out.go
index 01f10fc0..21063faa 100644
--- a/plugin/maxmind/common_out.go
+++ b/plugin/maxmind/common_out.go
@@ -8,8 +8,8 @@ import (
"strings"
"github.com/Loyalsoldier/geoip/lib"
- "github.com/oschwald/geoip2-golang"
- "github.com/oschwald/maxminddb-golang"
+ "github.com/oschwald/geoip2-golang/v2"
+ "github.com/oschwald/maxminddb-golang/v2"
)
var (
@@ -20,6 +20,15 @@ var (
defaultIPInfoOutputDir = filepath.Join("./", "output", "ipinfo")
)
+// Reference: https://github.com/oschwald/geoip2-golang/blob/HEAD/models.go
+var (
+ zeroDBIPLanguageNames dbipLanguageNames
+ zeroDBIPContinent dbipContinent
+ zeroDBIPCountryRecord dbipCountryRecord
+ zeroDBIPRepresentedCountry dbipRepresentedCountry
+ zeroDBIPCountry dbipCountry
+)
+
// Reference: https://ipinfo.io/lite
type ipInfoLite struct {
ASN string `maxminddb:"asn"`
@@ -31,6 +40,66 @@ type ipInfoLite struct {
CountryCode string `maxminddb:"country_code"`
}
+// Reference: https://github.com/oschwald/geoip2-golang/blob/HEAD/models.go
+type dbipLanguageNames struct {
+ geoip2.Names
+
+ // Persian localized name
+ Persian string `json:"fa,omitzero" maxminddb:"fa"`
+ // Korean localized name
+ Korean string `json:"ko,omitzero" maxminddb:"ko"`
+}
+
+func (d dbipLanguageNames) HasData() bool {
+ return d != zeroDBIPLanguageNames
+}
+
+// Reference: https://github.com/oschwald/geoip2-golang/blob/HEAD/models.go
+type dbipContinent struct {
+ geoip2.Continent
+
+ Names dbipLanguageNames `json:"names,omitzero" maxminddb:"names"`
+}
+
+func (d dbipContinent) HasData() bool {
+ return d != zeroDBIPContinent
+}
+
+// Reference: https://github.com/oschwald/geoip2-golang/blob/HEAD/models.go
+type dbipCountryRecord struct {
+ geoip2.CountryRecord
+
+ Names dbipLanguageNames `json:"names,omitzero" maxminddb:"names"`
+}
+
+func (d dbipCountryRecord) HasData() bool {
+ return d != zeroDBIPCountryRecord
+}
+
+// Reference: https://github.com/oschwald/geoip2-golang/blob/HEAD/models.go
+type dbipRepresentedCountry struct {
+ geoip2.RepresentedCountry
+
+ Names dbipLanguageNames `json:"names,omitzero" maxminddb:"names"`
+}
+
+func (d dbipRepresentedCountry) HasData() bool {
+ return d != zeroDBIPRepresentedCountry
+}
+
+// Reference: https://github.com/oschwald/geoip2-golang/blob/HEAD/models.go
+type dbipCountry struct {
+ Traits geoip2.CountryTraits `json:"traits,omitzero" maxminddb:"traits"`
+ Continent dbipContinent `json:"continent,omitzero" maxminddb:"continent"`
+ RepresentedCountry dbipRepresentedCountry `json:"represented_country,omitzero" maxminddb:"represented_country"`
+ Country dbipCountryRecord `json:"country,omitzero" maxminddb:"country"`
+ RegisteredCountry dbipCountryRecord `json:"registered_country,omitzero" maxminddb:"registered_country"`
+}
+
+func (d dbipCountry) HasData() bool {
+ return d != zeroDBIPCountry
+}
+
func newGeoLite2CountryMMDBOut(iType string, iDesc string, action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
var tmp struct {
OutputName string `json:"outputName"`
@@ -98,26 +167,25 @@ func (g *GeoLite2CountryMMDBOut) GetExtraInfo() (map[string]any, error) {
return nil, err
}
- db, err := maxminddb.FromBytes(content)
+ db, err := maxminddb.OpenBytes(content)
if err != nil {
return nil, err
}
defer db.Close()
infoList := make(map[string]any)
- networks := db.Networks(maxminddb.SkipAliasedNetworks)
- for networks.Next() {
+ for network := range db.Networks() {
switch g.Type {
- case TypeGeoLite2CountryMMDBOut, TypeDBIPCountryMMDBOut:
+ case TypeGeoLite2CountryMMDBOut:
var record geoip2.Country
- _, err := networks.Network(&record)
+ err := network.Decode(&record)
if err != nil {
return nil, err
}
switch {
- case strings.TrimSpace(record.Country.IsoCode) != "":
- countryCode := strings.ToUpper(strings.TrimSpace(record.Country.IsoCode))
+ case strings.TrimSpace(record.Country.ISOCode) != "":
+ countryCode := strings.ToUpper(strings.TrimSpace(record.Country.ISOCode))
if _, found := infoList[countryCode]; !found {
infoList[countryCode] = geoip2.Country{
Continent: record.Continent,
@@ -125,8 +193,8 @@ func (g *GeoLite2CountryMMDBOut) GetExtraInfo() (map[string]any, error) {
}
}
- case strings.TrimSpace(record.RegisteredCountry.IsoCode) != "":
- countryCode := strings.ToUpper(strings.TrimSpace(record.RegisteredCountry.IsoCode))
+ case strings.TrimSpace(record.RegisteredCountry.ISOCode) != "":
+ countryCode := strings.ToUpper(strings.TrimSpace(record.RegisteredCountry.ISOCode))
if _, found := infoList[countryCode]; !found {
infoList[countryCode] = geoip2.Country{
Continent: record.Continent,
@@ -134,19 +202,14 @@ func (g *GeoLite2CountryMMDBOut) GetExtraInfo() (map[string]any, error) {
}
}
- case strings.TrimSpace(record.RepresentedCountry.IsoCode) != "":
- countryCode := strings.ToUpper(strings.TrimSpace(record.RepresentedCountry.IsoCode))
+ case strings.TrimSpace(record.RepresentedCountry.ISOCode) != "":
+ countryCode := strings.ToUpper(strings.TrimSpace(record.RepresentedCountry.ISOCode))
if _, found := infoList[countryCode]; !found {
infoList[countryCode] = geoip2.Country{
Continent: record.Continent,
- Country: struct {
- Names map[string]string `maxminddb:"names"`
- IsoCode string `maxminddb:"iso_code"`
- GeoNameID uint `maxminddb:"geoname_id"`
- IsInEuropeanUnion bool `maxminddb:"is_in_european_union"`
- }{
+ Country: geoip2.CountryRecord{
Names: record.RepresentedCountry.Names,
- IsoCode: record.RepresentedCountry.IsoCode,
+ ISOCode: record.RepresentedCountry.ISOCode,
GeoNameID: record.RepresentedCountry.GeoNameID,
IsInEuropeanUnion: record.RepresentedCountry.IsInEuropeanUnion,
},
@@ -154,9 +217,52 @@ func (g *GeoLite2CountryMMDBOut) GetExtraInfo() (map[string]any, error) {
}
}
+ case TypeDBIPCountryMMDBOut:
+ var record dbipCountry
+ err := network.Decode(&record)
+ if err != nil {
+ return nil, err
+ }
+
+ switch {
+ case strings.TrimSpace(record.Country.ISOCode) != "":
+ countryCode := strings.ToUpper(strings.TrimSpace(record.Country.ISOCode))
+ if _, found := infoList[countryCode]; !found {
+ infoList[countryCode] = dbipCountry{
+ Continent: record.Continent,
+ Country: record.Country,
+ }
+ }
+
+ case strings.TrimSpace(record.RegisteredCountry.ISOCode) != "":
+ countryCode := strings.ToUpper(strings.TrimSpace(record.RegisteredCountry.ISOCode))
+ if _, found := infoList[countryCode]; !found {
+ infoList[countryCode] = dbipCountry{
+ Continent: record.Continent,
+ Country: record.RegisteredCountry,
+ }
+ }
+
+ case strings.TrimSpace(record.RepresentedCountry.ISOCode) != "":
+ countryCode := strings.ToUpper(strings.TrimSpace(record.RepresentedCountry.ISOCode))
+ if _, found := infoList[countryCode]; !found {
+ infoList[countryCode] = dbipCountry{
+ Continent: record.Continent,
+ Country: dbipCountryRecord{
+ CountryRecord: geoip2.CountryRecord{
+ ISOCode: record.RepresentedCountry.ISOCode,
+ GeoNameID: record.RepresentedCountry.GeoNameID,
+ IsInEuropeanUnion: record.RepresentedCountry.IsInEuropeanUnion,
+ },
+ Names: record.RepresentedCountry.Names,
+ },
+ }
+ }
+ }
+
case TypeIPInfoCountryMMDBOut:
var record ipInfoLite
- _, err := networks.Network(&record)
+ err := network.Decode(&record)
if err != nil {
return nil, err
}
@@ -174,10 +280,6 @@ func (g *GeoLite2CountryMMDBOut) GetExtraInfo() (map[string]any, error) {
}
- if networks.Err() != nil {
- return nil, networks.Err()
- }
-
if len(infoList) == 0 {
return nil, fmt.Errorf("❌ [type %s | action %s] no extra info found in the source MMDB file: %s", g.Type, g.Action, g.SourceMMDBURI)
}
diff --git a/plugin/maxmind/maxmind_country_mmdb_in.go b/plugin/maxmind/maxmind_country_mmdb_in.go
index ab8be53f..be867b9b 100644
--- a/plugin/maxmind/maxmind_country_mmdb_in.go
+++ b/plugin/maxmind/maxmind_country_mmdb_in.go
@@ -3,13 +3,12 @@ package maxmind
import (
"encoding/json"
"fmt"
- "net"
"os"
"strings"
"github.com/Loyalsoldier/geoip/lib"
- "github.com/oschwald/geoip2-golang"
- "github.com/oschwald/maxminddb-golang"
+ "github.com/oschwald/geoip2-golang/v2"
+ "github.com/oschwald/maxminddb-golang/v2"
)
const (
@@ -97,38 +96,36 @@ func (g *GeoLite2CountryMMDBIn) Input(container lib.Container) (lib.Container, e
}
func (g *GeoLite2CountryMMDBIn) generateEntries(content []byte, entries map[string]*lib.Entry) error {
- db, err := maxminddb.FromBytes(content)
+ db, err := maxminddb.OpenBytes(content)
if err != nil {
return err
}
defer db.Close()
- networks := db.Networks(maxminddb.SkipAliasedNetworks)
- for networks.Next() {
+ for network := range db.Networks() {
var name string
- var subnet *net.IPNet
var err error
switch g.Type {
case TypeGeoLite2CountryMMDBIn, TypeDBIPCountryMMDBIn:
var record geoip2.Country
- subnet, err = networks.Network(&record)
+ err = network.Decode(&record)
if err != nil {
return err
}
switch {
- case strings.TrimSpace(record.Country.IsoCode) != "":
- name = strings.ToUpper(strings.TrimSpace(record.Country.IsoCode))
- case strings.TrimSpace(record.RegisteredCountry.IsoCode) != "":
- name = strings.ToUpper(strings.TrimSpace(record.RegisteredCountry.IsoCode))
- case strings.TrimSpace(record.RepresentedCountry.IsoCode) != "":
- name = strings.ToUpper(strings.TrimSpace(record.RepresentedCountry.IsoCode))
+ case strings.TrimSpace(record.Country.ISOCode) != "":
+ name = strings.ToUpper(strings.TrimSpace(record.Country.ISOCode))
+ case strings.TrimSpace(record.RegisteredCountry.ISOCode) != "":
+ name = strings.ToUpper(strings.TrimSpace(record.RegisteredCountry.ISOCode))
+ case strings.TrimSpace(record.RepresentedCountry.ISOCode) != "":
+ name = strings.ToUpper(strings.TrimSpace(record.RepresentedCountry.ISOCode))
}
case TypeIPInfoCountryMMDBIn:
var record ipInfoLite
- subnet, err = networks.Network(&record)
+ err = network.Decode(&record)
if err != nil {
return err
}
@@ -138,7 +135,7 @@ func (g *GeoLite2CountryMMDBIn) generateEntries(content []byte, entries map[stri
return lib.ErrNotSupportedFormat
}
- if name == "" || subnet == nil {
+ if name == "" || !network.Found() {
continue
}
@@ -151,16 +148,12 @@ func (g *GeoLite2CountryMMDBIn) generateEntries(content []byte, entries map[stri
entry = lib.NewEntry(name)
}
- if err := entry.AddPrefix(subnet); err != nil {
+ if err := entry.AddPrefix(network.Prefix()); err != nil {
return err
}
entries[name] = entry
}
- if networks.Err() != nil {
- return networks.Err()
- }
-
return nil
}
diff --git a/plugin/maxmind/maxmind_country_mmdb_out.go b/plugin/maxmind/maxmind_country_mmdb_out.go
index 7cba249e..4cf4cef6 100644
--- a/plugin/maxmind/maxmind_country_mmdb_out.go
+++ b/plugin/maxmind/maxmind_country_mmdb_out.go
@@ -12,7 +12,7 @@ import (
"github.com/Loyalsoldier/geoip/lib"
"github.com/maxmind/mmdbwriter"
"github.com/maxmind/mmdbwriter/mmdbtype"
- "github.com/oschwald/geoip2-golang"
+ "github.com/oschwald/geoip2-golang/v2"
)
const (
@@ -58,16 +58,19 @@ func (g *GeoLite2CountryMMDBOut) GetDescription() string {
func (g *GeoLite2CountryMMDBOut) Output(container lib.Container) error {
dbName := ""
dbDesc := ""
- recordSize := 28
+ dbLanguages := []string{"en"}
+ recordSize := 24
switch g.Type {
case TypeGeoLite2CountryMMDBOut:
dbName = "GeoLite2-Country"
dbDesc = "Customized GeoLite2 Country database"
+ dbLanguages = []string{"de", "en", "es", "fr", "ja", "pt-BR", "ru", "zh-CN"}
case TypeDBIPCountryMMDBOut:
dbName = "DBIP-Country-Lite"
dbDesc = "Customized DB-IP Country Lite database"
+ dbLanguages = []string{"de", "en", "es", "fr", "ja", "pt-BR", "ru", "zh-CN", "fa", "ko"}
case TypeIPInfoCountryMMDBOut:
dbName = "IPInfo-Lite"
@@ -79,6 +82,7 @@ func (g *GeoLite2CountryMMDBOut) Output(container lib.Container) error {
mmdbwriter.Options{
DatabaseType: dbName,
Description: map[string]string{"en": dbDesc},
+ Languages: dbLanguages,
RecordSize: recordSize,
IncludeReservedNetworks: true,
},
@@ -222,28 +226,28 @@ func (g *GeoLite2CountryMMDBOut) marshalData(writer *mmdbwriter.Tree, entry *lib
record = mmdbtype.Map{
"continent": mmdbtype.Map{
"names": mmdbtype.Map{
- "de": mmdbtype.String(info.Continent.Names["de"]),
- "en": mmdbtype.String(info.Continent.Names["en"]),
- "es": mmdbtype.String(info.Continent.Names["es"]),
- "fr": mmdbtype.String(info.Continent.Names["fr"]),
- "ja": mmdbtype.String(info.Continent.Names["ja"]),
- "pt-BR": mmdbtype.String(info.Continent.Names["pt-BR"]),
- "ru": mmdbtype.String(info.Continent.Names["ru"]),
- "zh-CN": mmdbtype.String(info.Continent.Names["zh-CN"]),
+ "de": mmdbtype.String(info.Continent.Names.German),
+ "en": mmdbtype.String(info.Continent.Names.English),
+ "es": mmdbtype.String(info.Continent.Names.Spanish),
+ "fr": mmdbtype.String(info.Continent.Names.French),
+ "ja": mmdbtype.String(info.Continent.Names.Japanese),
+ "pt-BR": mmdbtype.String(info.Continent.Names.BrazilianPortuguese),
+ "ru": mmdbtype.String(info.Continent.Names.Russian),
+ "zh-CN": mmdbtype.String(info.Continent.Names.SimplifiedChinese),
},
"code": mmdbtype.String(info.Continent.Code),
"geoname_id": mmdbtype.Uint32(info.Continent.GeoNameID),
},
"country": mmdbtype.Map{
"names": mmdbtype.Map{
- "de": mmdbtype.String(info.Country.Names["de"]),
- "en": mmdbtype.String(info.Country.Names["en"]),
- "es": mmdbtype.String(info.Country.Names["es"]),
- "fr": mmdbtype.String(info.Country.Names["fr"]),
- "ja": mmdbtype.String(info.Country.Names["ja"]),
- "pt-BR": mmdbtype.String(info.Country.Names["pt-BR"]),
- "ru": mmdbtype.String(info.Country.Names["ru"]),
- "zh-CN": mmdbtype.String(info.Country.Names["zh-CN"]),
+ "de": mmdbtype.String(info.Country.Names.German),
+ "en": mmdbtype.String(info.Country.Names.English),
+ "es": mmdbtype.String(info.Country.Names.Spanish),
+ "fr": mmdbtype.String(info.Country.Names.French),
+ "ja": mmdbtype.String(info.Country.Names.Japanese),
+ "pt-BR": mmdbtype.String(info.Country.Names.BrazilianPortuguese),
+ "ru": mmdbtype.String(info.Country.Names.Russian),
+ "zh-CN": mmdbtype.String(info.Country.Names.SimplifiedChinese),
},
"iso_code": mmdbtype.String(entry.GetName()),
"geoname_id": mmdbtype.Uint32(info.Country.GeoNameID),
@@ -254,14 +258,14 @@ func (g *GeoLite2CountryMMDBOut) marshalData(writer *mmdbwriter.Tree, entry *lib
record = mmdbtype.Map{
"country": mmdbtype.Map{
"names": mmdbtype.Map{
- "de": mmdbtype.String(info.Country.Names["de"]),
- "en": mmdbtype.String(info.Country.Names["en"]),
- "es": mmdbtype.String(info.Country.Names["es"]),
- "fr": mmdbtype.String(info.Country.Names["fr"]),
- "ja": mmdbtype.String(info.Country.Names["ja"]),
- "pt-BR": mmdbtype.String(info.Country.Names["pt-BR"]),
- "ru": mmdbtype.String(info.Country.Names["ru"]),
- "zh-CN": mmdbtype.String(info.Country.Names["zh-CN"]),
+ "de": mmdbtype.String(info.Country.Names.German),
+ "en": mmdbtype.String(info.Country.Names.English),
+ "es": mmdbtype.String(info.Country.Names.Spanish),
+ "fr": mmdbtype.String(info.Country.Names.French),
+ "ja": mmdbtype.String(info.Country.Names.Japanese),
+ "pt-BR": mmdbtype.String(info.Country.Names.BrazilianPortuguese),
+ "ru": mmdbtype.String(info.Country.Names.Russian),
+ "zh-CN": mmdbtype.String(info.Country.Names.SimplifiedChinese),
},
"iso_code": mmdbtype.String(entry.GetName()),
"geoname_id": mmdbtype.Uint32(info.Country.GeoNameID),
@@ -271,7 +275,7 @@ func (g *GeoLite2CountryMMDBOut) marshalData(writer *mmdbwriter.Tree, entry *lib
}
case TypeDBIPCountryMMDBOut:
- info, found := extraInfo[entry.GetName()].(geoip2.Country)
+ info, found := extraInfo[entry.GetName()].(dbipCountry)
if !found {
log.Printf("⚠️ [type %s | action %s] not found extra info for list %s\n", g.Type, g.Action, entry.GetName())
@@ -284,32 +288,32 @@ func (g *GeoLite2CountryMMDBOut) marshalData(writer *mmdbwriter.Tree, entry *lib
record = mmdbtype.Map{
"continent": mmdbtype.Map{
"names": mmdbtype.Map{
- "de": mmdbtype.String(info.Continent.Names["de"]),
- "en": mmdbtype.String(info.Continent.Names["en"]),
- "es": mmdbtype.String(info.Continent.Names["es"]),
- "fa": mmdbtype.String(info.Continent.Names["fa"]),
- "fr": mmdbtype.String(info.Continent.Names["fr"]),
- "ja": mmdbtype.String(info.Continent.Names["ja"]),
- "ko": mmdbtype.String(info.Continent.Names["ko"]),
- "pt-BR": mmdbtype.String(info.Continent.Names["pt-BR"]),
- "ru": mmdbtype.String(info.Continent.Names["ru"]),
- "zh-CN": mmdbtype.String(info.Continent.Names["zh-CN"]),
+ "de": mmdbtype.String(info.Continent.Names.German),
+ "en": mmdbtype.String(info.Continent.Names.English),
+ "es": mmdbtype.String(info.Continent.Names.Spanish),
+ "fa": mmdbtype.String(info.Continent.Names.Persian),
+ "fr": mmdbtype.String(info.Continent.Names.French),
+ "ja": mmdbtype.String(info.Continent.Names.Japanese),
+ "ko": mmdbtype.String(info.Continent.Names.Korean),
+ "pt-BR": mmdbtype.String(info.Continent.Names.BrazilianPortuguese),
+ "ru": mmdbtype.String(info.Continent.Names.Russian),
+ "zh-CN": mmdbtype.String(info.Continent.Names.SimplifiedChinese),
},
"code": mmdbtype.String(info.Continent.Code),
"geoname_id": mmdbtype.Uint32(info.Continent.GeoNameID),
},
"country": mmdbtype.Map{
"names": mmdbtype.Map{
- "de": mmdbtype.String(info.Country.Names["de"]),
- "en": mmdbtype.String(info.Country.Names["en"]),
- "es": mmdbtype.String(info.Country.Names["es"]),
- "fa": mmdbtype.String(info.Country.Names["fa"]),
- "fr": mmdbtype.String(info.Country.Names["fr"]),
- "ja": mmdbtype.String(info.Country.Names["ja"]),
- "ko": mmdbtype.String(info.Country.Names["ko"]),
- "pt-BR": mmdbtype.String(info.Country.Names["pt-BR"]),
- "ru": mmdbtype.String(info.Country.Names["ru"]),
- "zh-CN": mmdbtype.String(info.Country.Names["zh-CN"]),
+ "de": mmdbtype.String(info.Country.Names.German),
+ "en": mmdbtype.String(info.Country.Names.English),
+ "es": mmdbtype.String(info.Country.Names.Spanish),
+ "fa": mmdbtype.String(info.Country.Names.Persian),
+ "fr": mmdbtype.String(info.Country.Names.French),
+ "ja": mmdbtype.String(info.Country.Names.Japanese),
+ "ko": mmdbtype.String(info.Country.Names.Korean),
+ "pt-BR": mmdbtype.String(info.Country.Names.BrazilianPortuguese),
+ "ru": mmdbtype.String(info.Country.Names.Russian),
+ "zh-CN": mmdbtype.String(info.Country.Names.SimplifiedChinese),
},
"iso_code": mmdbtype.String(entry.GetName()),
"geoname_id": mmdbtype.Uint32(info.Country.GeoNameID),
@@ -320,16 +324,16 @@ func (g *GeoLite2CountryMMDBOut) marshalData(writer *mmdbwriter.Tree, entry *lib
record = mmdbtype.Map{
"country": mmdbtype.Map{
"names": mmdbtype.Map{
- "de": mmdbtype.String(info.Country.Names["de"]),
- "en": mmdbtype.String(info.Country.Names["en"]),
- "es": mmdbtype.String(info.Country.Names["es"]),
- "fa": mmdbtype.String(info.Country.Names["fa"]),
- "fr": mmdbtype.String(info.Country.Names["fr"]),
- "ja": mmdbtype.String(info.Country.Names["ja"]),
- "ko": mmdbtype.String(info.Country.Names["ko"]),
- "pt-BR": mmdbtype.String(info.Country.Names["pt-BR"]),
- "ru": mmdbtype.String(info.Country.Names["ru"]),
- "zh-CN": mmdbtype.String(info.Country.Names["zh-CN"]),
+ "de": mmdbtype.String(info.Country.Names.German),
+ "en": mmdbtype.String(info.Country.Names.English),
+ "es": mmdbtype.String(info.Country.Names.Spanish),
+ "fa": mmdbtype.String(info.Country.Names.Persian),
+ "fr": mmdbtype.String(info.Country.Names.French),
+ "ja": mmdbtype.String(info.Country.Names.Japanese),
+ "ko": mmdbtype.String(info.Country.Names.Korean),
+ "pt-BR": mmdbtype.String(info.Country.Names.BrazilianPortuguese),
+ "ru": mmdbtype.String(info.Country.Names.Russian),
+ "zh-CN": mmdbtype.String(info.Country.Names.SimplifiedChinese),
},
"iso_code": mmdbtype.String(entry.GetName()),
"geoname_id": mmdbtype.Uint32(info.Country.GeoNameID),