diff --git a/kittens/choose_files/main.go b/kittens/choose_files/main.go index d7065a79c..e34da0d78 100644 --- a/kittens/choose_files/main.go +++ b/kittens/choose_files/main.go @@ -19,6 +19,7 @@ import ( "github.com/kovidgoyal/kitty/tools/tui/loop" "github.com/kovidgoyal/kitty/tools/tui/readline" "github.com/kovidgoyal/kitty/tools/utils" + "golang.org/x/text/message" ) var _ = fmt.Print @@ -204,6 +205,7 @@ type Handler struct { rl *readline.Readline err_chan chan error shortcut_tracker config.ShortcutTracker + msg_printer *message.Printer } func (h *Handler) draw_screen() (err error) { @@ -734,7 +736,7 @@ func main(_ *cli.Command, opts *Options, args []string) (rc int, err error) { return 1, err } lp.MouseTrackingMode(loop.FULL_MOUSE_TRACKING) - handler := Handler{lp: lp, err_chan: make(chan error, 8)} + handler := Handler{lp: lp, err_chan: make(chan error, 8), msg_printer: message.NewPrinter(utils.LanguageTag())} handler.rl = readline.New(lp, readline.RlInit{ Prompt: "> ", ContinuationPrompt: ". ", Completer: handler.complete_save_prompt, }) diff --git a/kittens/choose_files/results.go b/kittens/choose_files/results.go index b57ff99d3..7544326b7 100644 --- a/kittens/choose_files/results.go +++ b/kittens/choose_files/results.go @@ -248,7 +248,7 @@ func (h *Handler) draw_num_of_matches(num_shown, y int) { case 0: m = " no matches " default: - m = fmt.Sprintf(" %d of %d matches ", min(num_shown, h.state.last_render.num_matches), h.state.last_render.num_matches) + m = fmt.Sprintf(" %d of %s matches ", min(num_shown, h.state.last_render.num_matches), h.msg_printer.Sprint(h.state.last_render.num_matches)) } w := int(math.Ceil(float64(wcswidth.Stringwidth(m)) / 2.0)) h.lp.MoveCursorTo(h.screen_size.width-w-2, y) diff --git a/tools/utils/misc.go b/tools/utils/misc.go index 281a5b5bf..0dbc411bf 100644 --- a/tools/utils/misc.go +++ b/tools/utils/misc.go @@ -15,6 +15,7 @@ import ( "sync" "golang.org/x/exp/constraints" + "golang.org/x/text/language" ) var _ = fmt.Print @@ -397,3 +398,28 @@ func Abs[T constraints.Integer](x T) T { } return x } + +var LanguageTag = sync.OnceValue(func() language.Tag { + // Check environment variables in order of precedence + var locale string + for _, v := range []string{"LC_ALL", "LC_MESSAGES", "LANG"} { + locale = os.Getenv(v) + if locale != "" { + break + } + } + if locale == "" { + return language.English // Default/fallback + } + // Remove encoding, e.g., ".UTF-8" + locale = strings.Split(locale, ".")[0] + // Replace underscore with hyphen to match BCP47 format (en_US -> en-US) + locale = strings.ReplaceAll(locale, "_", "-") + // Validate/normalize with golang.org/x/text/language + tag, err := language.Parse(locale) + if err != nil { + return language.English + } + return tag + +})