VideoTools/vendor/github.com/nicksnyder/go-i18n/v2/i18n/bundle.go
Stu Leak 68df790d27 Fix player frame generation and video playback
Major improvements to UnifiedPlayer:

1. GetFrameImage() now works when paused for responsive UI updates
2. Play() method properly starts FFmpeg process
3. Frame display loop runs continuously for smooth video display
4. Disabled audio temporarily to fix video playback fundamentals
5. Simplified FFmpeg command to focus on video stream only

Player now:
- Generates video frames correctly
- Shows video when paused
- Has responsive progress tracking
- Starts playback properly

Next steps: Re-enable audio playback once video is stable
2026-01-07 22:20:00 -05:00

145 lines
4.2 KiB
Go

package i18n
import (
"fmt"
"os"
"github.com/nicksnyder/go-i18n/v2/internal/plural"
"golang.org/x/text/language"
)
// UnmarshalFunc unmarshals data into v.
type UnmarshalFunc func(data []byte, v interface{}) error
// Bundle stores a set of messages and pluralization rules.
// Most applications only need a single bundle
// that is initialized early in the application's lifecycle.
// It is not goroutine safe to modify the bundle while Localizers
// are reading from it.
type Bundle struct {
defaultLanguage language.Tag
unmarshalFuncs map[string]UnmarshalFunc
messageTemplates map[language.Tag]map[string]*MessageTemplate
pluralRules plural.Rules
tags []language.Tag
matcher language.Matcher
}
// artTag is the language tag used for artificial languages
// https://en.wikipedia.org/wiki/Codes_for_constructed_languages
var artTag = language.MustParse("art")
// NewBundle returns a bundle with a default language and a default set of plural rules.
func NewBundle(defaultLanguage language.Tag) *Bundle {
b := &Bundle{
defaultLanguage: defaultLanguage,
pluralRules: plural.DefaultRules(),
}
b.pluralRules[artTag] = b.pluralRules.Rule(language.English)
b.addTag(defaultLanguage)
return b
}
// RegisterUnmarshalFunc registers an UnmarshalFunc for format.
func (b *Bundle) RegisterUnmarshalFunc(format string, unmarshalFunc UnmarshalFunc) {
if b.unmarshalFuncs == nil {
b.unmarshalFuncs = make(map[string]UnmarshalFunc)
}
b.unmarshalFuncs[format] = unmarshalFunc
}
// LoadMessageFile loads the bytes from path
// and then calls ParseMessageFileBytes.
func (b *Bundle) LoadMessageFile(path string) (*MessageFile, error) {
buf, err := os.ReadFile(path)
if err != nil {
return nil, err
}
return b.ParseMessageFileBytes(buf, path)
}
// MustLoadMessageFile is similar to LoadMessageFile
// except it panics if an error happens.
func (b *Bundle) MustLoadMessageFile(path string) {
if _, err := b.LoadMessageFile(path); err != nil {
panic(err)
}
}
// ParseMessageFileBytes parses the bytes in buf to add translations to the bundle.
//
// The format of the file is everything after the last ".".
//
// The language tag of the file is everything after the second to last "." or after the last path separator, but before the format.
func (b *Bundle) ParseMessageFileBytes(buf []byte, path string) (*MessageFile, error) {
messageFile, err := ParseMessageFileBytes(buf, path, b.unmarshalFuncs)
if err != nil {
return nil, err
}
if err := b.AddMessages(messageFile.Tag, messageFile.Messages...); err != nil {
return nil, err
}
return messageFile, nil
}
// MustParseMessageFileBytes is similar to ParseMessageFileBytes
// except it panics if an error happens.
func (b *Bundle) MustParseMessageFileBytes(buf []byte, path string) {
if _, err := b.ParseMessageFileBytes(buf, path); err != nil {
panic(err)
}
}
// AddMessages adds messages for a language.
// It is useful if your messages are in a format not supported by ParseMessageFileBytes.
func (b *Bundle) AddMessages(tag language.Tag, messages ...*Message) error {
pluralRule := b.pluralRules.Rule(tag)
if pluralRule == nil {
return fmt.Errorf("no plural rule registered for %s", tag)
}
if b.messageTemplates == nil {
b.messageTemplates = map[language.Tag]map[string]*MessageTemplate{}
}
if b.messageTemplates[tag] == nil {
b.messageTemplates[tag] = map[string]*MessageTemplate{}
b.addTag(tag)
}
for _, m := range messages {
b.messageTemplates[tag][m.ID] = NewMessageTemplate(m)
}
return nil
}
// MustAddMessages is similar to AddMessages except it panics if an error happens.
func (b *Bundle) MustAddMessages(tag language.Tag, messages ...*Message) {
if err := b.AddMessages(tag, messages...); err != nil {
panic(err)
}
}
func (b *Bundle) addTag(tag language.Tag) {
for _, t := range b.tags {
if t == tag {
// Tag already exists
return
}
}
b.tags = append(b.tags, tag)
b.matcher = language.NewMatcher(b.tags)
}
// LanguageTags returns the list of language tags
// of all the translations loaded into the bundle
func (b *Bundle) LanguageTags() []language.Tag {
return b.tags
}
func (b *Bundle) getMessageTemplate(tag language.Tag, id string) *MessageTemplate {
templates := b.messageTemplates[tag]
if templates == nil {
return nil
}
return templates[id]
}