feat: sync visible product branding
Sync telesrv c779c48 (feat(branding): unify visible product naming). Skipped private www files and preserved public README files; mapped orange appearance seed names to public default names.
This commit is contained in:
parent
da6a57e1a3
commit
2848ff0987
34 changed files with 449 additions and 91 deletions
|
|
@ -7,6 +7,7 @@ import (
|
|||
"golang.org/x/sync/singleflight"
|
||||
"golang.org/x/text/unicode/bidi"
|
||||
|
||||
"telesrv/internal/branding"
|
||||
"telesrv/internal/domain"
|
||||
"telesrv/internal/store"
|
||||
)
|
||||
|
|
@ -18,16 +19,34 @@ type Service struct {
|
|||
languageCache *languageListCache
|
||||
packLoads singleflight.Group
|
||||
languageLoads singleflight.Group
|
||||
publicBaseURL string
|
||||
}
|
||||
|
||||
// Option configures user-visible language-pack projection.
|
||||
type Option func(*Service)
|
||||
|
||||
// WithPublicBaseURL replaces official public hosts embedded in upstream
|
||||
// language-pack values with this deployment's public link root.
|
||||
func WithPublicBaseURL(value string) Option {
|
||||
return func(s *Service) {
|
||||
if strings.TrimSpace(value) != "" {
|
||||
s.publicBaseURL = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NewService 创建 langpack 服务。
|
||||
func NewService(packs store.LangPackStore) *Service {
|
||||
return newServiceWithCacheLimits(
|
||||
func NewService(packs store.LangPackStore, opts ...Option) *Service {
|
||||
s := newServiceWithCacheLimits(
|
||||
packs,
|
||||
defaultLangPackCacheMaxBytes,
|
||||
defaultLangPackCacheMaxEntries,
|
||||
defaultLanguageListCacheMaxEntries,
|
||||
)
|
||||
for _, opt := range opts {
|
||||
opt(s)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func newServiceWithCacheLimits(packs store.LangPackStore, maxBytes int64, maxEntries, languageEntries int) *Service {
|
||||
|
|
@ -35,6 +54,7 @@ func newServiceWithCacheLimits(packs store.LangPackStore, maxBytes int64, maxEnt
|
|||
packs: packs,
|
||||
packCache: newLangPackCache(maxBytes, maxEntries),
|
||||
languageCache: newLanguageListCache(languageEntries),
|
||||
publicBaseURL: branding.DefaultPublicURL,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -135,7 +155,11 @@ func shouldOverlayWebA(langPack string) bool {
|
|||
func (s *Service) rawPack(ctx context.Context, langPack, langCode string) (domain.LangPack, error) {
|
||||
key := langPackCacheKey{pack: langPack, code: langCode, kind: langPackCacheRaw}
|
||||
return s.cachedPack(ctx, key, func() (domain.LangPack, error) {
|
||||
return s.packs.GetPack(ctx, langPack, langCode, 0)
|
||||
pack, err := s.packs.GetPack(ctx, langPack, langCode, 0)
|
||||
if err != nil {
|
||||
return domain.LangPack{}, err
|
||||
}
|
||||
return s.brandPack(pack), nil
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -218,6 +242,7 @@ func (s *Service) cachedLanguages(ctx context.Context, langPack string) ([]domai
|
|||
}
|
||||
for i := range languages {
|
||||
languages[i] = completeLanguageMetadata(langPack, languages[i])
|
||||
languages[i] = s.brandLanguage(languages[i])
|
||||
}
|
||||
return cachedLanguagesLoadResult{
|
||||
languages: languages,
|
||||
|
|
@ -237,6 +262,27 @@ func (s *Service) cachedLanguages(ctx context.Context, langPack string) ([]domai
|
|||
}
|
||||
}
|
||||
|
||||
func (s *Service) brandPack(pack domain.LangPack) domain.LangPack {
|
||||
for i := range pack.Strings {
|
||||
item := &pack.Strings[i]
|
||||
item.Value = branding.UserVisibleText(item.Value, s.publicBaseURL)
|
||||
item.ZeroValue = branding.UserVisibleText(item.ZeroValue, s.publicBaseURL)
|
||||
item.OneValue = branding.UserVisibleText(item.OneValue, s.publicBaseURL)
|
||||
item.TwoValue = branding.UserVisibleText(item.TwoValue, s.publicBaseURL)
|
||||
item.FewValue = branding.UserVisibleText(item.FewValue, s.publicBaseURL)
|
||||
item.ManyValue = branding.UserVisibleText(item.ManyValue, s.publicBaseURL)
|
||||
item.OtherValue = branding.UserVisibleText(item.OtherValue, s.publicBaseURL)
|
||||
}
|
||||
return pack
|
||||
}
|
||||
|
||||
func (s *Service) brandLanguage(lang domain.LangPackLanguage) domain.LangPackLanguage {
|
||||
lang.Name = branding.UserVisibleText(lang.Name, s.publicBaseURL)
|
||||
lang.NativeName = branding.UserVisibleText(lang.NativeName, s.publicBaseURL)
|
||||
lang.TranslationsURL = branding.UserVisibleText(lang.TranslationsURL, s.publicBaseURL)
|
||||
return lang
|
||||
}
|
||||
|
||||
func (s *Service) flushCaches() {
|
||||
if s == nil {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -74,6 +74,66 @@ func TestServiceNormalizesWebARawLangCode(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestServiceRebrandsEveryLanguagePackProjection(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
base := memory.NewLangPackStore()
|
||||
seed := domain.LangPack{
|
||||
LangPack: "weba",
|
||||
LangCode: "en",
|
||||
Version: 7,
|
||||
Strings: []domain.LangPackString{
|
||||
{Key: "AppName", Value: "Telegram", Pluralized: true, ZeroValue: "No Telegram accounts", OneValue: "One Telegram account", TwoValue: "Two Telegram accounts", FewValue: "Few Telegram accounts", ManyValue: "Many Telegram accounts", OtherValue: "Other Telegram accounts"},
|
||||
{Key: "TranslationLink", Value: "https://translations.telegram.org/en"},
|
||||
{Key: "RuntimeIdentifier", Value: "org.telegram.messenger"},
|
||||
},
|
||||
}
|
||||
if err := base.UpsertPack(ctx, seed); err != nil {
|
||||
t.Fatalf("seed langpack: %v", err)
|
||||
}
|
||||
storeWithMetadata := &metadataLangPackStore{
|
||||
LangPackStore: base,
|
||||
languages: []domain.LangPackLanguage{{
|
||||
LangPack: "weba",
|
||||
LangCode: "en",
|
||||
Name: "Telegram English",
|
||||
NativeName: "Telegram English",
|
||||
TranslationsURL: "https://translations.telegram.org/en",
|
||||
}},
|
||||
}
|
||||
svc := NewService(storeWithMetadata, WithPublicBaseURL("https://chat.example/root/"))
|
||||
|
||||
for name, load := range map[string]func() (domain.LangPack, error){
|
||||
"full": func() (domain.LangPack, error) { return svc.GetLangPack(ctx, "weba", "en") },
|
||||
"difference": func() (domain.LangPack, error) { return svc.GetDifference(ctx, "weba", "en", 1) },
|
||||
"keys": func() (domain.LangPack, error) {
|
||||
return svc.GetStrings(ctx, "weba", "en", []string{"AppName", "TranslationLink", "RuntimeIdentifier"})
|
||||
},
|
||||
} {
|
||||
pack, err := load()
|
||||
if err != nil {
|
||||
t.Fatalf("%s projection: %v", name, err)
|
||||
}
|
||||
appName := findLangPackString(pack.Strings, "AppName")
|
||||
if appName == nil || appName.Value != "Telesrv" || appName.ZeroValue != "No Telesrv accounts" || appName.OneValue != "One Telesrv account" || appName.TwoValue != "Two Telesrv accounts" || appName.FewValue != "Few Telesrv accounts" || appName.ManyValue != "Many Telesrv accounts" || appName.OtherValue != "Other Telesrv accounts" {
|
||||
t.Fatalf("%s AppName = %+v, want all value forms rebranded", name, appName)
|
||||
}
|
||||
if got := stringValue(pack.Strings, "TranslationLink"); got != "https://chat.example/root/en" {
|
||||
t.Fatalf("%s TranslationLink = %q", name, got)
|
||||
}
|
||||
if got := stringValue(pack.Strings, "RuntimeIdentifier"); got != "org.telegram.messenger" {
|
||||
t.Fatalf("%s RuntimeIdentifier = %q, want protocol identifier unchanged", name, got)
|
||||
}
|
||||
}
|
||||
|
||||
languages, err := svc.ListLanguages(ctx, "weba")
|
||||
if err != nil {
|
||||
t.Fatalf("list languages: %v", err)
|
||||
}
|
||||
if len(languages) != 1 || languages[0].Name != "Telesrv English" || languages[0].NativeName != "Telesrv English" || languages[0].TranslationsURL != "https://chat.example/root/en" {
|
||||
t.Fatalf("languages = %+v, want branded metadata", languages)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListLanguagesUsesSeededPacks(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
packs := memory.NewLangPackStore()
|
||||
|
|
@ -286,6 +346,15 @@ type countingLangPackStore struct {
|
|||
listLanguages int
|
||||
}
|
||||
|
||||
type metadataLangPackStore struct {
|
||||
store.LangPackStore
|
||||
languages []domain.LangPackLanguage
|
||||
}
|
||||
|
||||
func (s *metadataLangPackStore) ListLanguages(context.Context, string) ([]domain.LangPackLanguage, error) {
|
||||
return append([]domain.LangPackLanguage(nil), s.languages...), nil
|
||||
}
|
||||
|
||||
func (s *countingLangPackStore) GetPack(ctx context.Context, langPack, langCode string, fromVersion int) (domain.LangPack, error) {
|
||||
s.mu.Lock()
|
||||
s.getPack++
|
||||
|
|
@ -334,3 +403,12 @@ func stringValue(strings []domain.LangPackString, key string) string {
|
|||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func findLangPackString(strings []domain.LangPackString, key string) *domain.LangPackString {
|
||||
for i := range strings {
|
||||
if strings[i].Key == key {
|
||||
return &strings[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue