mirror of
https://github.com/go-gitea/gitea
synced 2025-07-22 18:28:37 +00:00
Support localized README (#20508)
* Support localized README * Slightly simplify getting the readme file and add some tests. Ensure that i18n also works for docs/ etc. Signed-off-by: Andrew Thornton <art27@cantab.net> * Update modules/markup/renderer.go * Update modules/markup/renderer.go * Update modules/markup/renderer.go Co-authored-by: Andrew Thornton <art27@cantab.net>
This commit is contained in:
@@ -57,7 +57,7 @@ type namedBlob struct {
|
||||
}
|
||||
|
||||
// FIXME: There has to be a more efficient way of doing this
|
||||
func getReadmeFileFromPath(commit *git.Commit, treePath string) (*namedBlob, error) {
|
||||
func getReadmeFileFromPath(ctx *context.Context, commit *git.Commit, treePath string) (*namedBlob, error) {
|
||||
tree, err := commit.SubTree(treePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -68,50 +68,33 @@ func getReadmeFileFromPath(commit *git.Commit, treePath string) (*namedBlob, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var readmeFiles [4]*namedBlob
|
||||
exts := []string{".md", ".txt", ""} // sorted by priority
|
||||
// Create a list of extensions in priority order
|
||||
// 1. Markdown files - with and without localisation - e.g. README.en-us.md or README.md
|
||||
// 2. Txt files - e.g. README.txt
|
||||
// 3. No extension - e.g. README
|
||||
exts := append(localizedExtensions(".md", ctx.Language()), ".txt", "") // sorted by priority
|
||||
extCount := len(exts)
|
||||
readmeFiles := make([]*namedBlob, extCount+1)
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
continue
|
||||
}
|
||||
for i, ext := range exts {
|
||||
if markup.IsReadmeFile(entry.Name(), ext) {
|
||||
if readmeFiles[i] == nil || base.NaturalSortLess(readmeFiles[i].name, entry.Blob().Name()) {
|
||||
name := entry.Name()
|
||||
isSymlink := entry.IsLink()
|
||||
target := entry
|
||||
if isSymlink {
|
||||
target, err = entry.FollowLinks()
|
||||
if err != nil && !git.IsErrBadLink(err) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if target != nil && (target.IsExecutable() || target.IsRegular()) {
|
||||
readmeFiles[i] = &namedBlob{
|
||||
name,
|
||||
isSymlink,
|
||||
target.Blob(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if markup.IsReadmeFile(entry.Name()) {
|
||||
if readmeFiles[3] == nil || base.NaturalSortLess(readmeFiles[3].name, entry.Blob().Name()) {
|
||||
if i, ok := markup.IsReadmeFileExtension(entry.Name(), exts...); ok {
|
||||
if readmeFiles[i] == nil || base.NaturalSortLess(readmeFiles[i].name, entry.Blob().Name()) {
|
||||
name := entry.Name()
|
||||
isSymlink := entry.IsLink()
|
||||
target := entry
|
||||
if isSymlink {
|
||||
entry, err = entry.FollowLinks()
|
||||
target, err = entry.FollowLinks()
|
||||
if err != nil && !git.IsErrBadLink(err) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if entry != nil && (entry.IsExecutable() || entry.IsRegular()) {
|
||||
readmeFiles[3] = &namedBlob{
|
||||
if target != nil && (target.IsExecutable() || target.IsRegular()) {
|
||||
readmeFiles[i] = &namedBlob{
|
||||
name,
|
||||
isSymlink,
|
||||
entry.Blob(),
|
||||
target.Blob(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -151,13 +134,38 @@ func renderDirectory(ctx *context.Context, treeLink string) {
|
||||
renderReadmeFile(ctx, readmeFile, readmeTreelink)
|
||||
}
|
||||
|
||||
// localizedExtensions prepends the provided language code with and without a
|
||||
// regional identifier to the provided extenstion.
|
||||
// Note: the language code will always be lower-cased, if a region is present it must be separated with a `-`
|
||||
// Note: ext should be prefixed with a `.`
|
||||
func localizedExtensions(ext, languageCode string) (localizedExts []string) {
|
||||
if len(languageCode) < 1 {
|
||||
return []string{ext}
|
||||
}
|
||||
|
||||
lowerLangCode := "." + strings.ToLower(languageCode)
|
||||
|
||||
if strings.Contains(lowerLangCode, "-") {
|
||||
underscoreLangCode := strings.ReplaceAll(lowerLangCode, "-", "_")
|
||||
indexOfDash := strings.Index(lowerLangCode, "-")
|
||||
// e.g. [.zh-cn.md, .zh_cn.md, .zh.md, .md]
|
||||
return []string{lowerLangCode + ext, underscoreLangCode + ext, lowerLangCode[:indexOfDash] + ext, ext}
|
||||
}
|
||||
|
||||
// e.g. [.en.md, .md]
|
||||
return []string{lowerLangCode + ext, ext}
|
||||
}
|
||||
|
||||
func findReadmeFile(ctx *context.Context, entries git.Entries, treeLink string) (*namedBlob, string) {
|
||||
// 3 for the extensions in exts[] in order
|
||||
// the last one is for a readme that doesn't
|
||||
// strictly match an extension
|
||||
var readmeFiles [4]*namedBlob
|
||||
var docsEntries [3]*git.TreeEntry
|
||||
exts := []string{".md", ".txt", ""} // sorted by priority
|
||||
// Create a list of extensions in priority order
|
||||
// 1. Markdown files - with and without localisation - e.g. README.en-us.md or README.md
|
||||
// 2. Txt files - e.g. README.txt
|
||||
// 3. No extension - e.g. README
|
||||
exts := append(localizedExtensions(".md", ctx.Language()), ".txt", "") // sorted by priority
|
||||
extCount := len(exts)
|
||||
readmeFiles := make([]*namedBlob, extCount+1)
|
||||
|
||||
docsEntries := make([]*git.TreeEntry, 3) // (one of docs/, .gitea/ or .github/)
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
lowerName := strings.ToLower(entry.Name())
|
||||
@@ -178,47 +186,24 @@ func findReadmeFile(ctx *context.Context, entries git.Entries, treeLink string)
|
||||
continue
|
||||
}
|
||||
|
||||
for i, ext := range exts {
|
||||
if markup.IsReadmeFile(entry.Name(), ext) {
|
||||
log.Debug("%s", entry.Name())
|
||||
name := entry.Name()
|
||||
isSymlink := entry.IsLink()
|
||||
target := entry
|
||||
if isSymlink {
|
||||
var err error
|
||||
target, err = entry.FollowLinks()
|
||||
if err != nil && !git.IsErrBadLink(err) {
|
||||
ctx.ServerError("FollowLinks", err)
|
||||
return nil, ""
|
||||
}
|
||||
}
|
||||
log.Debug("%t", target == nil)
|
||||
if target != nil && (target.IsExecutable() || target.IsRegular()) {
|
||||
readmeFiles[i] = &namedBlob{
|
||||
name,
|
||||
isSymlink,
|
||||
target.Blob(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if markup.IsReadmeFile(entry.Name()) {
|
||||
if i, ok := markup.IsReadmeFileExtension(entry.Name(), exts...); ok {
|
||||
log.Debug("Potential readme file: %s", entry.Name())
|
||||
name := entry.Name()
|
||||
isSymlink := entry.IsLink()
|
||||
target := entry
|
||||
if isSymlink {
|
||||
var err error
|
||||
entry, err = entry.FollowLinks()
|
||||
target, err = entry.FollowLinks()
|
||||
if err != nil && !git.IsErrBadLink(err) {
|
||||
ctx.ServerError("FollowLinks", err)
|
||||
return nil, ""
|
||||
}
|
||||
}
|
||||
if entry != nil && (entry.IsExecutable() || entry.IsRegular()) {
|
||||
readmeFiles[3] = &namedBlob{
|
||||
if target != nil && (target.IsExecutable() || target.IsRegular()) {
|
||||
readmeFiles[i] = &namedBlob{
|
||||
name,
|
||||
isSymlink,
|
||||
entry.Blob(),
|
||||
target.Blob(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -239,7 +224,7 @@ func findReadmeFile(ctx *context.Context, entries git.Entries, treeLink string)
|
||||
continue
|
||||
}
|
||||
var err error
|
||||
readmeFile, err = getReadmeFileFromPath(ctx.Repo.Commit, entry.GetSubJumpablePathName())
|
||||
readmeFile, err = getReadmeFileFromPath(ctx, ctx.Repo.Commit, entry.GetSubJumpablePathName())
|
||||
if err != nil {
|
||||
ctx.ServerError("getReadmeFileFromPath", err)
|
||||
return nil, ""
|
||||
|
Reference in New Issue
Block a user