code: func (sp *SourceSpec) NewFileInfo(baseDir, filename string, isLeafBundle bool, fi os.FileInfo) *FileInfo {
  
  	var lang, translationBaseName, relPath string
  
  	if fp, ok := fi.(hugofs.FilePather); ok {
  		filename = fp.Filename()
  		baseDir = fp.BaseDir()
  		relPath = fp.Path()
  	}
  
  	if fl, ok := fi.(hugofs.LanguageAnnouncer); ok {
  		lang = fl.Lang()
  		translationBaseName = fl.TranslationBaseName()
  	}
  
  	dir, name := filepath.Split(filename)
  	if !strings.HasSuffix(dir, helpers.FilePathSeparator) {
  		dir = dir + helpers.FilePathSeparator
  	}
  
  	baseDir = strings.TrimSuffix(baseDir, helpers.FilePathSeparator)
  
  	relDir := ""
  	if dir != baseDir {
  		relDir = strings.TrimPrefix(dir, baseDir)
  	}
  
  	relDir = strings.TrimPrefix(relDir, helpers.FilePathSeparator)
  
  	if relPath == "" {
  		relPath = filepath.Join(relDir, name)
  	}
  
  	ext := strings.ToLower(strings.TrimPrefix(filepath.Ext(name), "."))
  	baseName := helpers.Filename(name)
  
  	if translationBaseName == "" {
  		// This is usyally provided by the filesystem. But this FileInfo is also
  		// created in a standalone context when doing "hugo new". This is
  		// an approximate implementation, which is "good enough" in that case.
  		fileLangExt := filepath.Ext(baseName)
  		translationBaseName = strings.TrimSuffix(baseName, fileLangExt)
  	}
  
  	f := &FileInfo{
  		sp:                  sp,
  		filename:            filename,
  		fi:                  fi,
  		lang:                lang,
  		ext:                 ext,
  		dir:                 dir,
  		relDir:              relDir,
  		relPath:             relPath,
  		name:                name,
  		baseName:            baseName,
  		translationBaseName: translationBaseName,
  		isLeafBundle:        isLeafBundle,
  	}
  
  	return f
  
  }
docs: // NewFileInfo returns a new FileInfo structure.