aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--daemon/daemon.go6
-rw-r--r--daemon/routes.go3
-rw-r--r--daemon/server.go5
-rw-r--r--errors/errors.go4
-rw-r--r--reader/atom/parser.go2
-rw-r--r--reader/atom/parser_test.go6
-rw-r--r--reader/feed/handler.go41
-rw-r--r--reader/feed/parser.go8
-rw-r--r--reader/json/parser.go2
-rw-r--r--reader/json/parser_test.go6
-rw-r--r--reader/opml/parser.go2
-rw-r--r--reader/opml/parser_test.go6
-rw-r--r--reader/rdf/parser.go2
-rw-r--r--reader/rdf/parser_test.go6
-rw-r--r--reader/rss/parser.go2
-rw-r--r--reader/rss/parser_test.go6
-rw-r--r--storage/user.go12
-rw-r--r--template/functions.go5
18 files changed, 59 insertions, 65 deletions
diff --git a/daemon/daemon.go b/daemon/daemon.go
index 9e1576d..f100159 100644
--- a/daemon/daemon.go
+++ b/daemon/daemon.go
@@ -12,6 +12,7 @@ import (
"time"
"github.com/miniflux/miniflux/config"
+ "github.com/miniflux/miniflux/locale"
"github.com/miniflux/miniflux/logger"
"github.com/miniflux/miniflux/reader/feed"
"github.com/miniflux/miniflux/scheduler"
@@ -26,9 +27,10 @@ func Run(cfg *config.Config, store *storage.Storage) {
signal.Notify(stop, os.Interrupt)
signal.Notify(stop, syscall.SIGTERM)
- feedHandler := feed.NewFeedHandler(store)
+ translator := locale.Load()
+ feedHandler := feed.NewFeedHandler(store, translator)
pool := scheduler.NewWorkerPool(feedHandler, cfg.WorkerPoolSize())
- server := newServer(cfg, store, pool, feedHandler)
+ server := newServer(cfg, store, pool, feedHandler, translator)
scheduler.NewFeedScheduler(
store,
diff --git a/daemon/routes.go b/daemon/routes.go
index 35cec9e..bb141f7 100644
--- a/daemon/routes.go
+++ b/daemon/routes.go
@@ -23,9 +23,8 @@ import (
"github.com/gorilla/mux"
)
-func routes(cfg *config.Config, store *storage.Storage, feedHandler *feed.Handler, pool *scheduler.WorkerPool) *mux.Router {
+func routes(cfg *config.Config, store *storage.Storage, feedHandler *feed.Handler, pool *scheduler.WorkerPool, translator *locale.Translator) *mux.Router {
router := mux.NewRouter()
- translator := locale.Load()
templateEngine := template.NewEngine(cfg, router, translator)
apiController := api.NewController(store, feedHandler)
diff --git a/daemon/server.go b/daemon/server.go
index 4e8ff32..6ac49bd 100644
--- a/daemon/server.go
+++ b/daemon/server.go
@@ -10,6 +10,7 @@ import (
"time"
"github.com/miniflux/miniflux/config"
+ "github.com/miniflux/miniflux/locale"
"github.com/miniflux/miniflux/logger"
"github.com/miniflux/miniflux/reader/feed"
"github.com/miniflux/miniflux/scheduler"
@@ -18,7 +19,7 @@ import (
"golang.org/x/crypto/acme/autocert"
)
-func newServer(cfg *config.Config, store *storage.Storage, pool *scheduler.WorkerPool, feedHandler *feed.Handler) *http.Server {
+func newServer(cfg *config.Config, store *storage.Storage, pool *scheduler.WorkerPool, feedHandler *feed.Handler, translator *locale.Translator) *http.Server {
certFile := cfg.CertFile()
keyFile := cfg.KeyFile()
certDomain := cfg.CertDomain()
@@ -28,7 +29,7 @@ func newServer(cfg *config.Config, store *storage.Storage, pool *scheduler.Worke
WriteTimeout: 10 * time.Second,
IdleTimeout: 60 * time.Second,
Addr: cfg.ListenAddr(),
- Handler: routes(cfg, store, feedHandler, pool),
+ Handler: routes(cfg, store, feedHandler, pool, translator),
}
if certDomain != "" && certCache != "" {
diff --git a/errors/errors.go b/errors/errors.go
index 71805ad..e7af7b1 100644
--- a/errors/errors.go
+++ b/errors/errors.go
@@ -27,6 +27,6 @@ func (l LocalizedError) Localize(translation *locale.Language) string {
}
// NewLocalizedError returns a new LocalizedError.
-func NewLocalizedError(message string, args ...interface{}) LocalizedError {
- return LocalizedError{message: message, args: args}
+func NewLocalizedError(message string, args ...interface{}) *LocalizedError {
+ return &LocalizedError{message: message, args: args}
}
diff --git a/reader/atom/parser.go b/reader/atom/parser.go
index 94b50c7..9a41dac 100644
--- a/reader/atom/parser.go
+++ b/reader/atom/parser.go
@@ -14,7 +14,7 @@ import (
)
// Parse returns a normalized feed struct from a Atom feed.
-func Parse(data io.Reader) (*model.Feed, error) {
+func Parse(data io.Reader) (*model.Feed, *errors.LocalizedError) {
atomFeed := new(atomFeed)
decoder := xml.NewDecoder(data)
decoder.CharsetReader = encoding.CharsetReader
diff --git a/reader/atom/parser_test.go b/reader/atom/parser_test.go
index ec9186c..bfd3d3a 100644
--- a/reader/atom/parser_test.go
+++ b/reader/atom/parser_test.go
@@ -8,8 +8,6 @@ import (
"bytes"
"testing"
"time"
-
- "github.com/miniflux/miniflux/errors"
)
func TestParseAtomSample(t *testing.T) {
@@ -430,8 +428,4 @@ func TestParseInvalidXml(t *testing.T) {
if err == nil {
t.Error("Parse should returns an error")
}
-
- if _, ok := err.(errors.LocalizedError); !ok {
- t.Error("The error returned must be a LocalizedError")
- }
}
diff --git a/reader/feed/handler.go b/reader/feed/handler.go
index d6ac84e..516593c 100644
--- a/reader/feed/handler.go
+++ b/reader/feed/handler.go
@@ -10,6 +10,7 @@ import (
"github.com/miniflux/miniflux/errors"
"github.com/miniflux/miniflux/http"
+ "github.com/miniflux/miniflux/locale"
"github.com/miniflux/miniflux/logger"
"github.com/miniflux/miniflux/model"
"github.com/miniflux/miniflux/reader/icon"
@@ -30,7 +31,8 @@ var (
// Handler contains all the logic to create and refresh feeds.
type Handler struct {
- store *storage.Storage
+ store *storage.Storage
+ translator *locale.Translator
}
// CreateFeed fetch, parse and store a new feed.
@@ -44,7 +46,7 @@ func (h *Handler) CreateFeed(userID, categoryID int64, url string, crawler bool)
client := http.NewClient(url)
response, err := client.Get()
if err != nil {
- if _, ok := err.(errors.LocalizedError); ok {
+ if _, ok := err.(*errors.LocalizedError); ok {
return nil, err
}
return nil, errors.NewLocalizedError(errRequestFailed, err)
@@ -68,9 +70,9 @@ func (h *Handler) CreateFeed(userID, categoryID int64, url string, crawler bool)
return nil, errors.NewLocalizedError(errEncoding, err)
}
- subscription, err := parseFeed(body)
- if err != nil {
- return nil, err
+ subscription, feedErr := parseFeed(body)
+ if feedErr != nil {
+ return nil, feedErr
}
feedProcessor := processor.NewFeedProcessor(userID, h.store, subscription)
@@ -110,6 +112,13 @@ func (h *Handler) CreateFeed(userID, categoryID int64, url string, crawler bool)
// RefreshFeed fetch and update a feed if necessary.
func (h *Handler) RefreshFeed(userID, feedID int64) error {
defer timer.ExecutionTime(time.Now(), fmt.Sprintf("[Handler:RefreshFeed] feedID=%d", feedID))
+ userLanguage, err := h.store.UserLanguage(userID)
+ if err != nil {
+ logger.Error("[Handler:RefreshFeed] %v", err)
+ userLanguage = "en_US"
+ }
+
+ currentLanguage := h.translator.GetLanguage(userLanguage)
originalFeed, err := h.store.FeedByID(userID, feedID)
if err != nil {
@@ -124,14 +133,14 @@ func (h *Handler) RefreshFeed(userID, feedID int64) error {
response, err := client.Get()
if err != nil {
var customErr errors.LocalizedError
- if lerr, ok := err.(errors.LocalizedError); ok {
- customErr = lerr
+ if lerr, ok := err.(*errors.LocalizedError); ok {
+ customErr = *lerr
} else {
- customErr = errors.NewLocalizedError(errRequestFailed, err)
+ customErr = *errors.NewLocalizedError(errRequestFailed, err)
}
originalFeed.ParsingErrorCount++
- originalFeed.ParsingErrorMsg = customErr.Error()
+ originalFeed.ParsingErrorMsg = customErr.Localize(currentLanguage)
h.store.UpdateFeed(originalFeed)
return customErr
}
@@ -141,7 +150,7 @@ func (h *Handler) RefreshFeed(userID, feedID int64) error {
if response.HasServerFailure() {
err := errors.NewLocalizedError(errServerFailure, response.StatusCode)
originalFeed.ParsingErrorCount++
- originalFeed.ParsingErrorMsg = err.Error()
+ originalFeed.ParsingErrorMsg = err.Localize(currentLanguage)
h.store.UpdateFeed(originalFeed)
return err
}
@@ -153,7 +162,7 @@ func (h *Handler) RefreshFeed(userID, feedID int64) error {
if response.ContentLength == 0 {
err := errors.NewLocalizedError(errEmptyFeed)
originalFeed.ParsingErrorCount++
- originalFeed.ParsingErrorMsg = err.Error()
+ originalFeed.ParsingErrorMsg = err.Localize(currentLanguage)
h.store.UpdateFeed(originalFeed)
return err
}
@@ -163,10 +172,10 @@ func (h *Handler) RefreshFeed(userID, feedID int64) error {
return errors.NewLocalizedError(errEncoding, err)
}
- subscription, err := parseFeed(body)
- if err != nil {
+ subscription, parseErr := parseFeed(body)
+ if parseErr != nil {
originalFeed.ParsingErrorCount++
- originalFeed.ParsingErrorMsg = err.Error()
+ originalFeed.ParsingErrorMsg = parseErr.Localize(currentLanguage)
h.store.UpdateFeed(originalFeed)
return err
}
@@ -209,6 +218,6 @@ func (h *Handler) RefreshFeed(userID, feedID int64) error {
}
// NewFeedHandler returns a feed handler.
-func NewFeedHandler(store *storage.Storage) *Handler {
- return &Handler{store: store}
+func NewFeedHandler(store *storage.Storage, translator *locale.Translator) *Handler {
+ return &Handler{store, translator}
}
diff --git a/reader/feed/parser.go b/reader/feed/parser.go
index 70c81e3..f76a071 100644
--- a/reader/feed/parser.go
+++ b/reader/feed/parser.go
@@ -7,11 +7,11 @@ package feed
import (
"bytes"
"encoding/xml"
- "errors"
"io"
"strings"
"time"
+ "github.com/miniflux/miniflux/errors"
"github.com/miniflux/miniflux/logger"
"github.com/miniflux/miniflux/model"
"github.com/miniflux/miniflux/reader/atom"
@@ -66,13 +66,13 @@ func DetectFeedFormat(r io.Reader) string {
return FormatUnknown
}
-func parseFeed(r io.Reader) (*model.Feed, error) {
+func parseFeed(r io.Reader) (*model.Feed, *errors.LocalizedError) {
defer timer.ExecutionTime(time.Now(), "[Feed:ParseFeed]")
var buffer bytes.Buffer
size, _ := io.Copy(&buffer, r)
if size == 0 {
- return nil, errors.New("This feed is empty")
+ return nil, errors.NewLocalizedError("This feed is empty")
}
str := stripInvalidXMLCharacters(buffer.String())
@@ -90,7 +90,7 @@ func parseFeed(r io.Reader) (*model.Feed, error) {
case FormatRDF:
return rdf.Parse(reader)
default:
- return nil, errors.New("Unsupported feed format")
+ return nil, errors.NewLocalizedError("Unsupported feed format")
}
}
diff --git a/reader/json/parser.go b/reader/json/parser.go
index 52b4809..ddd3e4f 100644
--- a/reader/json/parser.go
+++ b/reader/json/parser.go
@@ -13,7 +13,7 @@ import (
)
// Parse returns a normalized feed struct from a JON feed.
-func Parse(data io.Reader) (*model.Feed, error) {
+func Parse(data io.Reader) (*model.Feed, *errors.LocalizedError) {
feed := new(jsonFeed)
decoder := json.NewDecoder(data)
if err := decoder.Decode(&feed); err != nil {
diff --git a/reader/json/parser_test.go b/reader/json/parser_test.go
index a3d5b5b..19c12c9 100644
--- a/reader/json/parser_test.go
+++ b/reader/json/parser_test.go
@@ -9,8 +9,6 @@ import (
"strings"
"testing"
"time"
-
- "github.com/miniflux/miniflux/errors"
)
func TestParseJsonFeed(t *testing.T) {
@@ -377,8 +375,4 @@ func TestParseInvalidJSON(t *testing.T) {
if err == nil {
t.Error("Parse should returns an error")
}
-
- if _, ok := err.(errors.LocalizedError); !ok {
- t.Error("The error returned must be a LocalizedError")
- }
}
diff --git a/reader/opml/parser.go b/reader/opml/parser.go
index 140acc5..b167d47 100644
--- a/reader/opml/parser.go
+++ b/reader/opml/parser.go
@@ -13,7 +13,7 @@ import (
)
// Parse reads an OPML file and returns a SubcriptionList.
-func Parse(data io.Reader) (SubcriptionList, error) {
+func Parse(data io.Reader) (SubcriptionList, *errors.LocalizedError) {
feeds := new(opml)
decoder := xml.NewDecoder(data)
decoder.CharsetReader = encoding.CharsetReader
diff --git a/reader/opml/parser_test.go b/reader/opml/parser_test.go
index 12c8048..e00d578 100644
--- a/reader/opml/parser_test.go
+++ b/reader/opml/parser_test.go
@@ -7,8 +7,6 @@ package opml
import (
"bytes"
"testing"
-
- "github.com/miniflux/miniflux/errors"
)
func TestParseOpmlWithoutCategories(t *testing.T) {
@@ -130,8 +128,4 @@ func TestParseInvalidXML(t *testing.T) {
if err == nil {
t.Error("Parse should generate an error")
}
-
- if _, ok := err.(errors.LocalizedError); !ok {
- t.Error("The error returned must be a LocalizedError")
- }
}
diff --git a/reader/rdf/parser.go b/reader/rdf/parser.go
index da82639..06cacec 100644
--- a/reader/rdf/parser.go
+++ b/reader/rdf/parser.go
@@ -14,7 +14,7 @@ import (
)
// Parse returns a normalized feed struct from a RDF feed.
-func Parse(data io.Reader) (*model.Feed, error) {
+func Parse(data io.Reader) (*model.Feed, *errors.LocalizedError) {
feed := new(rdfFeed)
decoder := xml.NewDecoder(data)
decoder.CharsetReader = encoding.CharsetReader
diff --git a/reader/rdf/parser_test.go b/reader/rdf/parser_test.go
index e025e53..52c11a5 100644
--- a/reader/rdf/parser_test.go
+++ b/reader/rdf/parser_test.go
@@ -9,8 +9,6 @@ import (
"strings"
"testing"
"time"
-
- "github.com/miniflux/miniflux/errors"
)
func TestParseRDFSample(t *testing.T) {
@@ -330,8 +328,4 @@ func TestParseInvalidXml(t *testing.T) {
if err == nil {
t.Error("Parse should returns an error")
}
-
- if _, ok := err.(errors.LocalizedError); !ok {
- t.Error("The error returned must be a LocalizedError")
- }
}
diff --git a/reader/rss/parser.go b/reader/rss/parser.go
index f5de561..328cde2 100644
--- a/reader/rss/parser.go
+++ b/reader/rss/parser.go
@@ -14,7 +14,7 @@ import (
)
// Parse returns a normalized feed struct from a RSS feed.
-func Parse(data io.Reader) (*model.Feed, error) {
+func Parse(data io.Reader) (*model.Feed, *errors.LocalizedError) {
feed := new(rssFeed)
decoder := xml.NewDecoder(data)
decoder.CharsetReader = encoding.CharsetReader
diff --git a/reader/rss/parser_test.go b/reader/rss/parser_test.go
index 7d72417..7bf9f75 100644
--- a/reader/rss/parser_test.go
+++ b/reader/rss/parser_test.go
@@ -8,8 +8,6 @@ import (
"bytes"
"testing"
"time"
-
- "github.com/miniflux/miniflux/errors"
)
func TestParseRss2Sample(t *testing.T) {
@@ -564,8 +562,4 @@ func TestParseInvalidXml(t *testing.T) {
if err == nil {
t.Error("Parse should returns an error")
}
-
- if _, ok := err.(errors.LocalizedError); !ok {
- t.Error("The error returned must be a LocalizedError")
- }
}
diff --git a/storage/user.go b/storage/user.go
index 5d64b65..41e565a 100644
--- a/storage/user.go
+++ b/storage/user.go
@@ -175,6 +175,18 @@ func (s *Storage) UpdateUser(user *model.User) error {
return nil
}
+// UserLanguage returns the language of the given user.
+func (s *Storage) UserLanguage(userID int64) (language string, err error) {
+ defer timer.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:UserLanguage] userID=%d", userID))
+ err = s.db.QueryRow(`SELECT language FROM users WHERE id = $1`, userID).Scan(&language)
+ if err == sql.ErrNoRows {
+ return "en_US", nil
+ } else if err != nil {
+ return "", fmt.Errorf("unable to fetch user language: %v", err)
+ }
+ return language, nil
+}
+
// UserByID finds a user by the ID.
func (s *Storage) UserByID(userID int64) (*model.User, error) {
defer timer.ExecutionTime(time.Now(), fmt.Sprintf("[Storage:UserByID] userID=%d", userID))
diff --git a/template/functions.go b/template/functions.go
index 08a4617..81ce1db 100644
--- a/template/functions.go
+++ b/template/functions.go
@@ -85,8 +85,9 @@ func (f *funcMap) Map() template.FuncMap {
case string:
return f.Language.Get(key.(string), args...)
case errors.LocalizedError:
- err := key.(errors.LocalizedError)
- return err.Localize(f.Language)
+ return key.(errors.LocalizedError).Localize(f.Language)
+ case *errors.LocalizedError:
+ return key.(*errors.LocalizedError).Localize(f.Language)
case error:
return key.(error).Error()
default: