...

Source file src/github.com/chai2010/gettext-go/fs_zip.go

Documentation: github.com/chai2010/gettext-go

     1  // Copyright 2013 ChaiShushan <chaishushan{AT}gmail.com>. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package gettext
     6  
     7  import (
     8  	"archive/zip"
     9  	"fmt"
    10  	"io/ioutil"
    11  	"sort"
    12  	"strings"
    13  )
    14  
    15  type zipFS struct {
    16  	root string
    17  	name string
    18  	r    *zip.Reader
    19  }
    20  
    21  func newZipFS(r *zip.Reader, name string) *zipFS {
    22  	fs := &zipFS{r: r, name: name}
    23  	fs.root = fs.zipRoot()
    24  	return fs
    25  }
    26  
    27  func (p *zipFS) zipName() string {
    28  	name := p.name
    29  	if x := strings.LastIndexAny(name, `\/`); x != -1 {
    30  		name = name[x+1:]
    31  	}
    32  	name = strings.TrimSuffix(name, ".zip")
    33  	return name
    34  }
    35  
    36  func (p *zipFS) zipRoot() string {
    37  	var somepath string
    38  	for _, f := range p.r.File {
    39  		if x := strings.Index(f.Name, "LC_MESSAGES"); x != -1 {
    40  			somepath = f.Name
    41  		}
    42  		if x := strings.Index(f.Name, "LC_RESOURCE"); x != -1 {
    43  			somepath = f.Name
    44  		}
    45  	}
    46  	if somepath == "" {
    47  		return p.zipName()
    48  	}
    49  
    50  	ss := strings.Split(somepath, "/")
    51  	for i, s := range ss {
    52  		// $(root)/$(lang)/LC_MESSAGES
    53  		// $(root)/$(lang)/LC_RESOURCE
    54  		if (s == "LC_MESSAGES" || s == "LC_RESOURCE") && i >= 2 {
    55  			return strings.Join(ss[:i-1], "/")
    56  		}
    57  	}
    58  
    59  	return p.zipName()
    60  }
    61  
    62  func (p *zipFS) LocaleList() []string {
    63  	var locals []string
    64  	for s := range p.lsZip(p.r) {
    65  		locals = append(locals, s)
    66  	}
    67  	sort.Strings(locals)
    68  	return locals
    69  }
    70  
    71  func (p *zipFS) LoadMessagesFile(domain, lang, ext string) ([]byte, error) {
    72  	trName := p.makeMessagesFileName(domain, lang, ext)
    73  	for _, f := range p.r.File {
    74  		if f.Name != trName {
    75  			continue
    76  		}
    77  		rc, err := f.Open()
    78  		if err != nil {
    79  			return nil, err
    80  		}
    81  		rcData, err := ioutil.ReadAll(rc)
    82  		rc.Close()
    83  		return rcData, err
    84  	}
    85  	return nil, fmt.Errorf("not found")
    86  }
    87  
    88  func (p *zipFS) LoadResourceFile(domain, lang, name string) ([]byte, error) {
    89  	rcName := p.makeResourceFileName(domain, lang, name)
    90  	for _, f := range p.r.File {
    91  		if f.Name != rcName {
    92  			continue
    93  		}
    94  		rc, err := f.Open()
    95  		if err != nil {
    96  			return nil, err
    97  		}
    98  		rcData, err := ioutil.ReadAll(rc)
    99  		rc.Close()
   100  		return rcData, err
   101  	}
   102  	return nil, fmt.Errorf("not found")
   103  }
   104  
   105  func (p *zipFS) String() string {
   106  	return "gettext.zipfs(" + p.name + ")"
   107  }
   108  
   109  func (p *zipFS) makeMessagesFileName(domain, lang, ext string) string {
   110  	return fmt.Sprintf("%s/%s/LC_MESSAGES/%s%s", p.root, lang, domain, ext)
   111  }
   112  
   113  func (p *zipFS) makeResourceFileName(domain, lang, name string) string {
   114  	return fmt.Sprintf("%s/%s/LC_RESOURCE/%s/%s", p.root, lang, domain, name)
   115  }
   116  
   117  func (p *zipFS) lsZip(r *zip.Reader) map[string]bool {
   118  	ssMap := make(map[string]bool)
   119  	for _, f := range r.File {
   120  		if x := strings.Index(f.Name, "LC_MESSAGES"); x != -1 {
   121  			s := strings.TrimRight(f.Name[:x], `\/`)
   122  			if x = strings.LastIndexAny(s, `\/`); x != -1 {
   123  				s = s[x+1:]
   124  			}
   125  			if s != "" {
   126  				ssMap[s] = true
   127  			}
   128  			continue
   129  		}
   130  		if x := strings.Index(f.Name, "LC_RESOURCE"); x != -1 {
   131  			s := strings.TrimRight(f.Name[:x], `\/`)
   132  			if x = strings.LastIndexAny(s, `\/`); x != -1 {
   133  				s = s[x+1:]
   134  			}
   135  			if s != "" {
   136  				ssMap[s] = true
   137  			}
   138  			continue
   139  		}
   140  	}
   141  	return ssMap
   142  }
   143  

View as plain text