translationProvider.go - hugo - [fork] hugo port for 9front
HTML git clone https://git.drkhsh.at/hugo.git
DIR Log
DIR Files
DIR Refs
DIR Submodules
DIR README
DIR LICENSE
---
translationProvider.go (3830B)
---
1 // Copyright 2017 The Hugo Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 package i18n
15
16 import (
17 "encoding/json"
18 "fmt"
19 "strings"
20
21 "github.com/gohugoio/hugo/common/paths"
22
23 "github.com/gohugoio/hugo/common/herrors"
24 "golang.org/x/text/language"
25 yaml "gopkg.in/yaml.v2"
26
27 "github.com/gohugoio/go-i18n/v2/i18n"
28 "github.com/gohugoio/hugo/helpers"
29 toml "github.com/pelletier/go-toml/v2"
30
31 "github.com/gohugoio/hugo/deps"
32 "github.com/gohugoio/hugo/hugofs"
33 "github.com/gohugoio/hugo/source"
34 )
35
36 // TranslationProvider provides translation handling, i.e. loading
37 // of bundles etc.
38 type TranslationProvider struct {
39 t Translator
40 }
41
42 // NewTranslationProvider creates a new translation provider.
43 func NewTranslationProvider() *TranslationProvider {
44 return &TranslationProvider{}
45 }
46
47 // Update updates the i18n func in the provided Deps.
48 func (tp *TranslationProvider) NewResource(dst *deps.Deps) error {
49 defaultLangTag, err := language.Parse(dst.Conf.DefaultContentLanguage())
50 if err != nil {
51 defaultLangTag = language.English
52 }
53 bundle := i18n.NewBundle(defaultLangTag)
54
55 bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)
56 bundle.RegisterUnmarshalFunc("yaml", yaml.Unmarshal)
57 bundle.RegisterUnmarshalFunc("yml", yaml.Unmarshal)
58 bundle.RegisterUnmarshalFunc("json", json.Unmarshal)
59
60 w := hugofs.NewWalkway(
61 hugofs.WalkwayConfig{
62 Fs: dst.BaseFs.I18n.Fs,
63 IgnoreFile: dst.SourceSpec.IgnoreFile,
64 PathParser: dst.SourceSpec.Cfg.PathParser(),
65 WalkFn: func(path string, info hugofs.FileMetaInfo) error {
66 if info.IsDir() {
67 return nil
68 }
69 return addTranslationFile(bundle, source.NewFileInfo(info))
70 },
71 })
72
73 if err := w.Walk(); err != nil {
74 return err
75 }
76
77 tp.t = NewTranslator(bundle, dst.Conf, dst.Log)
78
79 dst.Translate = tp.t.Func(dst.Conf.Language().Lang)
80
81 return nil
82 }
83
84 const artificialLangTagPrefix = "art-x-"
85
86 func addTranslationFile(bundle *i18n.Bundle, r *source.File) error {
87 f, err := r.FileInfo().Meta().Open()
88 if err != nil {
89 return fmt.Errorf("failed to open translations file %q:: %w", r.LogicalName(), err)
90 }
91
92 b := helpers.ReaderToBytes(f)
93 f.Close()
94
95 name := r.LogicalName()
96 lang := paths.Filename(name)
97 tag := language.Make(lang)
98 if tag == language.Und {
99 try := artificialLangTagPrefix + lang
100 _, err = language.Parse(try)
101 if err != nil {
102 return fmt.Errorf("%q: %s", try, err)
103 }
104 name = artificialLangTagPrefix + name
105 }
106
107 _, err = bundle.ParseMessageFileBytes(b, name)
108 if err != nil {
109 if strings.Contains(err.Error(), "no plural rule") {
110 // https://github.com/gohugoio/hugo/issues/7798
111 name = artificialLangTagPrefix + name
112 _, err = bundle.ParseMessageFileBytes(b, name)
113 if err == nil {
114 return nil
115 }
116 }
117 return errWithFileContext(fmt.Errorf("failed to load translations: %w", err), r)
118 }
119
120 return nil
121 }
122
123 // CloneResource sets the language func for the new language.
124 func (tp *TranslationProvider) CloneResource(dst, src *deps.Deps) error {
125 dst.Translate = tp.t.Func(dst.Conf.Language().Lang)
126 return nil
127 }
128
129 func errWithFileContext(inerr error, r *source.File) error {
130 meta := r.FileInfo().Meta()
131 realFilename := meta.Filename
132 f, err := meta.Open()
133 if err != nil {
134 return inerr
135 }
136 defer f.Close()
137
138 return herrors.NewFileErrorFromName(inerr, realFilename).UpdateContent(f, nil)
139 }