Embed translation bundle into binary
This commit is contained in:
parent
2c82ccb324
commit
9fad7ef3a6
9 changed files with 43 additions and 42 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
||||||
|
*.pem
|
||||||
.idea/
|
.idea/
|
||||||
/cacert-idp
|
/cacert-idp
|
||||||
/static
|
/static
|
||||||
|
|
7
Makefile
7
Makefile
|
@ -1,6 +1,6 @@
|
||||||
GOFILES = $(wildcard */*.go)
|
GOFILES = $(wildcard */*.go)
|
||||||
TEMPLATES = $(wildcard ui/templates/*.gohtml)
|
TEMPLATES = $(wildcard ui/templates/*.gohtml)
|
||||||
TRANSLATIONS = $(wildcard active.*.toml)
|
TRANSLATIONS = $(wildcard translations/active.*.toml)
|
||||||
RESOURCES = ui/css ui/images ui/js
|
RESOURCES = ui/css ui/images ui/js
|
||||||
|
|
||||||
all: cacert-idp
|
all: cacert-idp
|
||||||
|
@ -18,8 +18,9 @@ go.sum: go.mod
|
||||||
go mod tidy
|
go mod tidy
|
||||||
|
|
||||||
translations: $(TRANSLATIONS) $(GOFILES)
|
translations: $(TRANSLATIONS) $(GOFILES)
|
||||||
goi18n extract .
|
cd translations ; \
|
||||||
goi18n merge active.*.toml
|
goi18n extract .. ; \
|
||||||
|
goi18n merge active.*.toml ; \
|
||||||
if translate.*.toml 2>/dev/null; then \
|
if translate.*.toml 2>/dev/null; then \
|
||||||
echo "missing translations"; \
|
echo "missing translations"; \
|
||||||
goi18n merge active.*.toml translate.*.toml; \
|
goi18n merge active.*.toml translate.*.toml; \
|
||||||
|
|
|
@ -147,9 +147,10 @@ func main() {
|
||||||
csrf.MaxAge(DefaultCSRFMaxAge))
|
csrf.MaxAge(DefaultCSRFMaxAge))
|
||||||
|
|
||||||
errorMiddleware, err := handlers.ErrorHandling(
|
errorMiddleware, err := handlers.ErrorHandling(
|
||||||
context.Background(),
|
|
||||||
logger,
|
logger,
|
||||||
ui.Templates,
|
ui.Templates,
|
||||||
|
bundle,
|
||||||
|
catalog,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatalf("could not initialize request error handling: %v", err)
|
logger.Fatalf("could not initialize request error handling: %v", err)
|
||||||
|
|
|
@ -130,9 +130,10 @@ func (w *errorResponseWriter) Write(content []byte) (int, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func ErrorHandling(
|
func ErrorHandling(
|
||||||
handlerContext context.Context,
|
|
||||||
logger *log.Logger,
|
logger *log.Logger,
|
||||||
templateFS fs.FS,
|
templateFS fs.FS,
|
||||||
|
bundle *i18n.Bundle,
|
||||||
|
messageCatalog *services.MessageCatalog,
|
||||||
) (func(http.Handler) http.Handler, error) {
|
) (func(http.Handler) http.Handler, error) {
|
||||||
errorTemplates, err := template.ParseFS(
|
errorTemplates, err := template.ParseFS(
|
||||||
templateFS,
|
templateFS,
|
||||||
|
@ -143,16 +144,6 @@ func ErrorHandling(
|
||||||
return nil, fmt.Errorf("could not parse templates: %w", err)
|
return nil, fmt.Errorf("could not parse templates: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
bundle, err := services.GetI18nBundle(handlerContext)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not get i18n bundle: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
messageCatalog, err := services.GetMessageCatalog(handlerContext)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not get message catalog: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(next http.Handler) http.Handler {
|
return func(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
errorBucket := &ErrorBucket{
|
errorBucket := &ErrorBucket{
|
||||||
|
|
|
@ -18,12 +18,13 @@ limitations under the License.
|
||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"git.cacert.org/oidc_idp/translations"
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/BurntSushi/toml"
|
||||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
"github.com/nicksnyder/go-i18n/v2/i18n"
|
||||||
"golang.org/x/text/language"
|
"golang.org/x/text/language"
|
||||||
|
@ -107,13 +108,6 @@ func AddMessages(catalog *MessageCatalog) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type contextKey int
|
|
||||||
|
|
||||||
const (
|
|
||||||
ctxI18nBundle contextKey = iota
|
|
||||||
ctxI18nCatalog
|
|
||||||
)
|
|
||||||
|
|
||||||
type MessageCatalog struct {
|
type MessageCatalog struct {
|
||||||
messages map[string]*i18n.Message
|
messages map[string]*i18n.Message
|
||||||
logger *log.Logger
|
logger *log.Logger
|
||||||
|
@ -227,10 +221,16 @@ func InitI18n(logger *log.Logger, languages []string) (*i18n.Bundle, *MessageCat
|
||||||
bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)
|
bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)
|
||||||
|
|
||||||
for _, lang := range languages {
|
for _, lang := range languages {
|
||||||
_, err := bundle.LoadMessageFile(fmt.Sprintf("active.%s.toml", lang))
|
bundleName := fmt.Sprintf("active.%s.toml", lang)
|
||||||
|
|
||||||
|
bundleBytes, err := translations.Bundles.ReadFile(bundleName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warnf("message bundle %s.toml not found", lang)
|
logger.Warnf("message bundle %s not found", bundleName)
|
||||||
|
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bundle.MustParseMessageFileBytes(bundleBytes, bundleName)
|
||||||
}
|
}
|
||||||
|
|
||||||
catalog := initMessageCatalog(logger)
|
catalog := initMessageCatalog(logger)
|
||||||
|
@ -247,19 +247,3 @@ func initMessageCatalog(logger *log.Logger) *MessageCatalog {
|
||||||
|
|
||||||
return &MessageCatalog{messages: messages, logger: logger}
|
return &MessageCatalog{messages: messages, logger: logger}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetI18nBundle(ctx context.Context) (*i18n.Bundle, error) {
|
|
||||||
if b, ok := ctx.Value(ctxI18nBundle).(*i18n.Bundle); ok {
|
|
||||||
return b, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, errors.New("context value is not a Bundle")
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetMessageCatalog(ctx context.Context) (*MessageCatalog, error) {
|
|
||||||
if c, ok := ctx.Value(ctxI18nCatalog).(*MessageCatalog); ok {
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, errors.New("context value is not a MessageCatalog")
|
|
||||||
}
|
|
||||||
|
|
23
translations/translations.go
Normal file
23
translations/translations.go
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020-2023 CAcert Inc.
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package translations
|
||||||
|
|
||||||
|
import "embed"
|
||||||
|
|
||||||
|
//go:embed active.*.toml
|
||||||
|
var Bundles embed.FS
|
|
@ -32,7 +32,7 @@
|
||||||
</main>
|
</main>
|
||||||
<footer class="footer mt-auto py-3">
|
<footer class="footer mt-auto py-3">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<span class="text-muted small">© 2020-2022 <a href="https://www.cacert.org/">CAcert</a></span>
|
<span class="text-muted small">© 2020-2023 <a href="https://www.cacert.org/">CAcert</a></span>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
<script type="text/javascript" src="/js/cacert.bundle.js"></script>
|
<script type="text/javascript" src="/js/cacert.bundle.js"></script>
|
||||||
|
|
Loading…
Reference in a new issue