From 2558a14d8ca7e1cbae5c082ecd0a02acf136b40e Mon Sep 17 00:00:00 2001 From: Maxim Lebedev Date: Mon, 13 Nov 2023 08:13:56 +0600 Subject: [PATCH] :building_construction: Support mono and multilang sites --- main.go | 61 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/main.go b/main.go index 7f39afa..e83ef30 100644 --- a/main.go +++ b/main.go @@ -25,7 +25,6 @@ import ( "github.com/caarlos0/env/v10" "golang.org/x/text/language" - "golang.org/x/text/message" "source.toby3d.me/toby3d/home/internal/common" "source.toby3d.me/toby3d/home/internal/domain" @@ -81,26 +80,9 @@ func NewApp(ctx context.Context, config *domain.Config) (*App, error) { pages := pagefsrepo.NewFileSystemPageRepository(contentDir) pager := pageucase.NewPageUseCase(pages, resources) - matcher := language.NewMatcher(message.DefaultCatalog.Languages()) - server := &http.Server{ Addr: config.AddrPort().String(), Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - head, tail := urlutil.ShiftPath(r.URL.Path) - - if head == "" { - tags, _, err := language.ParseAcceptLanguage(r.Header.Get(common.HeaderAcceptLanguage)) - if err != nil || len(tags) == 0 { - tags = append(tags, language.English) - } - - lang, _, _ := matcher.Match(tags...) - - http.Redirect(w, r, "/"+lang.String()+"/", http.StatusSeeOther) - - return - } - // TODO(toby3d): use exists static use case or split that on static and resource modules? // INFO(toby3d): any static file is public and unprotected by design, so it's safe to search it // first before deep down to any page or it's resource which might be secured by middleware or @@ -112,8 +94,7 @@ func NewApp(ctx context.Context, config *domain.Config) (*App, error) { return } - lang := domain.NewLanguage(head) - r.URL.Path = tail + lang := domain.LanguageUnd s, err := siter.Do(r.Context(), lang) if err != nil { @@ -122,6 +103,46 @@ func NewApp(ctx context.Context, config *domain.Config) (*App, error) { return } + if s.IsMultiLingual() { + head, tail := urlutil.ShiftPath(r.URL.Path) + + if head == "" { + supported := make([]language.Tag, len(s.Languages)) + for i := range s.Languages { + supported[i] = language.Make(s.Languages[i].Lang()) + } + + if s.DefaultLanguage != domain.LanguageUnd { + supported = append( + []language.Tag{language.Make(s.DefaultLanguage.Code())}, + supported..., + ) + } + + requested, _, err := language.ParseAcceptLanguage( + r.Header.Get(common.HeaderAcceptLanguage)) + if err != nil || len(requested) == 0 { + requested = append(requested, language.English) + } + + matched, _, _ := language.NewMatcher(supported).Match(requested...) + lang = domain.NewLanguage(matched.String()) + + http.Redirect(w, r, "/"+lang.Lang()+"/", http.StatusSeeOther) + + return + } + + lang = domain.NewLanguage(head) + r.URL.Path = tail + } + + if s, err = siter.Do(r.Context(), lang); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + + return + } + p, err := pager.Do(r.Context(), lang, r.URL.Path) if err != nil { if !errors.Is(err, page.ErrNotExist) {