tpl: Fix language handling in partials

We now use the same code path for all templates re this.

Fixes #13612
This commit is contained in:
Bjørn Erik Pedersen 2025-04-15 09:05:24 +02:00
parent 01667275d4
commit d61b9fc605
4 changed files with 55 additions and 44 deletions

View file

@ -724,7 +724,7 @@ func (p *Path) IsContentData() bool {
return p.pathType == TypeContentData
}
func (p Path) ForBundleType(t Type) *Path {
func (p Path) ForType(t Type) *Path {
p.pathType = t
return &p
}

View file

@ -180,7 +180,7 @@ func (t *pageTrees) collectAndMarkStaleIdentities(p *paths.Path) []identity.Iden
if p.Component() == files.ComponentFolderContent {
// It may also be a bundled content resource.
key := p.ForBundleType(paths.TypeContentResource).Base()
key := p.ForType(paths.TypeContentResource).Base()
tree = t.treeResources
nCount = 0
tree.ForEeachInDimension(key, doctree.DimensionLanguage.Index(),

View file

@ -564,14 +564,21 @@ func (s *TemplateStore) LookupPagesLayout(q TemplateQuery) *TemplInfo {
func (s *TemplateStore) LookupPartial(pth string) *TemplInfo {
ti, _ := s.cacheLookupPartials.GetOrCreate(pth, func() (*TemplInfo, error) {
d := s.templateDescriptorFromPath(pth)
desc := d.Desc
if desc.LayoutFromTemplate != "" {
panic("shortcode template descriptor must not have a layout")
pi := s.opts.PathParser.Parse(files.ComponentFolderLayouts, pth).ForType(paths.TypePartial)
k1, _, _, desc, err := s.toKeyCategoryAndDescriptor(pi)
if err != nil {
return nil, err
}
if desc.OutputFormat == "" && desc.MediaType == "" {
// Assume HTML.
desc.OutputFormat = s.htmlFormat.Name
desc.MediaType = s.htmlFormat.MediaType.Type
desc.IsPlainText = s.htmlFormat.IsPlainText
}
best := s.getBest()
defer s.putBest(best)
s.findBestMatchGet(s.key(path.Join(containerPartials, d.Path)), CategoryPartial, nil, desc, best)
s.findBestMatchGet(s.key(path.Join(containerPartials, k1)), CategoryPartial, nil, desc, best)
return best.templ, nil
})
@ -1486,43 +1493,6 @@ type PathTemplateDescriptor struct {
Desc TemplateDescriptor
}
// templateDescriptorFromPath returns a template descriptor from the given path.
// This is currently used in partial lookups only.
func (s *TemplateStore) templateDescriptorFromPath(pth string) PathTemplateDescriptor {
var (
mt media.Type
of output.Format
)
// Common cases.
dotCount := strings.Count(pth, ".")
if dotCount <= 1 {
if dotCount == 0 {
// Asume HTML.
of, mt = s.resolveOutputFormatAndOrMediaType("html", "")
} else {
pth = strings.TrimPrefix(pth, "/")
ext := path.Ext(pth)
pth = strings.TrimSuffix(pth, ext)
ext = ext[1:]
of, mt = s.resolveOutputFormatAndOrMediaType("", ext)
}
} else {
path := s.opts.PathParser.Parse(files.ComponentFolderLayouts, pth)
pth = path.PathNoIdentifier()
of, mt = s.resolveOutputFormatAndOrMediaType(path.OutputFormat(), path.Ext())
}
return PathTemplateDescriptor{
Path: pth,
Desc: TemplateDescriptor{
OutputFormat: of.Name,
MediaType: mt.Type,
IsPlainText: of.IsPlainText,
},
}
}
// resolveOutputFormatAndOrMediaType resolves the output format and/or media type
// based on the given output format suffix and media type suffix.
// Either of the suffixes can be empty, and the function will try to find a match

View file

@ -1163,3 +1163,44 @@ All.
// Just make sure it doesn't fail.
hugolib.Test(t, files)
}
func TestPartialsLangIssue13612(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
disableKinds = ['page','section','sitemap','taxonomy','term']
defaultContentLanguage = 'ru'
defaultContentLanguageInSubdir = true
[languages.ru]
weight = 1
[languages.en]
weight = 2
[outputs]
home = ['html','rss']
-- layouts/_partials/comment.en.html --
layouts/_partials/comment.en.html
-- layouts/_partials/comment.en.xml --
layouts/_partials/comment.en.xml
-- layouts/_partials/comment.ru.html --
layouts/_partials/comment.ru.html
-- layouts/_partials/comment.ru.xml --
layouts/_partials/comment.ru.xml
-- layouts/home.html --
{{ partial (print "comment." (default "ru" .Lang) ".html") . }}
-- layouts/home.rss.xml --
{{ partial (print "comment." (default "ru" .Lang) ".xml") . }}
`
b := hugolib.Test(t, files)
b.AssertFileContent("public/en/index.html", "layouts/_partials/comment.en.html")
b.AssertFileContent("public/en/index.xml", "layouts/_partials/comment.en.xml") // fail
b.AssertFileContent("public/ru/index.html", "layouts/_partials/comment.ru.html") // fail
b.AssertFileContent("public/ru/index.xml", "layouts/_partials/comment.ru.xml") // fail
}