Skip to content

Commit

Permalink
feat: support i18n across systems (#188)
Browse files Browse the repository at this point in the history
Signed-off-by: Neko Ayaka <[email protected]>
  • Loading branch information
nekomeowww authored Mar 4, 2024
1 parent a1e7082 commit b6e3e0c
Show file tree
Hide file tree
Showing 25 changed files with 327 additions and 43 deletions.
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,7 @@
# Log level, default is `info`, available options are `debug`, `info`, `warn`, `error`
# 日志级别,默认值为 `info`,可用选项为 `debug`、`info`、`warn`、`error`
# LOG_LEVEL=info

# Locales directory, default is `locales`, it is recommended to configure as an absolute path
# 本地化目录,默认值为 `locales`,推荐配置为绝对路径
# LOCALES_DIR=locales
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# syntax=docker/dockerfile:1

# --- builder ---

FROM golang:1.21 as builder

RUN GO111MODULE=on
Expand All @@ -23,8 +22,10 @@ FROM debian as runner
RUN apt update && apt upgrade -y && apt install -y ca-certificates curl && update-ca-certificates

COPY --from=builder /app/insights-bot/release/insights-bot /usr/local/bin/
COPY --from=builder /app/insights-bot/locales /etc/insights-bot/locales

ENV LOG_FILE_PATH /var/log/insights-bot/insights-bot.log
ENV LOCALES_DIR /etc/insights-bot/locales

EXPOSE 7069

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ docker buildx build --platform linux/arm64,linux/amd64 -t <tag> -f Dockerfile .
| `REDIS_CLIENT_CACHE_ENABLED` | `false` | `false` | Redis client cache enabled, default is `false`, read more about client cache at [https://redis.io/docs/manual/client-side-caching/](https://redis.io/docs/manual/client-side-caching/) and [https://github.com/redis/rueidis#client-side-caching](https://github.com/redis/rueidis#client-side-caching) for more details. |
| `LOG_FILE_PATH` | `false` | `<insights-bot_executable>/logs/insights-bot.log` | Log file path, you can specify one if you want to specify a path to store logs when executed and ran with binary. The default path is `/var/log/insights-bot/insights-bot.log` in Docker volume, you can override the defaults `-e LOG_FILE_PATH=<path>` when executing `docker run` command or modify and prepend a new `LOG_FILE_PATH` the `docker-compose.yml` file. |
| `LOG_LEVEL` | `false` | `info` | Log level, available values are `debug`, `info`, `warn`, `error` |
| `LOCALES_DIR` | `false` | `locales` | Locales directory, default is `locales`, it is recommended to configure as an absolute path. |

## Acknowledgements

Expand Down
1 change: 1 addition & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ docker buildx build --platform linux/arm64,linux/amd64 -t <tag> -f Dockerfile .
| `REDIS_CLIENT_CACHE_ENABLED` | `false` | `false` | 是否开启 Redis 客户端缓存,默认为 `false`, 你可以在这里了解更多相关的知识:[https://redis.io/docs/manual/client-side-caching/](https://redis.io/docs/manual/client-side-caching/) 以及 [https://github.com/redis/rueidis#client-side-caching](https://github.com/redis/rueidis#client-side-caching)|
| `LOG_FILE_PATH` | `false` | `<insights-bot_executable>/logs/insights-bot.log` | 日志文件路径,如果你想指定二进制执行和运行时存储日志的路径,可以指定一个。默认路径是 Docker 卷中的 `/var/log/insights-bot/insights-bot.log`,你可以在执行 `docker run` 命令时覆盖默认路径 `-e LOG_FILE_PATH=<path>` 或修改并在 `docker-compose.yml` 文件中预置新的 `LOG_FILE_PATH`|
| `LOG_LEVEL` | `false` | `info` | 日志等级,可选值为 `debug``info``warn``error`|
| `LOCALES_DIR` | `false` | `locales` | 本地化目录,默认值为 `locales`,推荐配置为绝对路径。 |

## 鸣谢

Expand Down
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ require (
github.com/nekomeowww/go-pinecone v0.1.0
github.com/nekomeowww/timecapsule/v2 v2.2.0
github.com/nekomeowww/xo v1.3.0
github.com/nicksnyder/go-i18n/v2 v2.4.0
github.com/pkoukk/tiktoken-go v0.1.6
github.com/redis/rueidis v1.0.23
github.com/samber/lo v1.39.0
Expand All @@ -33,6 +34,8 @@ require (
go.uber.org/multierr v1.11.0
go.uber.org/ratelimit v0.3.0
go.uber.org/zap v1.26.0
golang.org/x/text v0.14.0
gopkg.in/yaml.v3 v3.0.1
)

require (
Expand Down Expand Up @@ -101,8 +104,6 @@ require (
golang.org/x/mod v0.14.0 // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.16.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ ariga.io/atlas v0.15.0 h1:9lwSVcO/D3WgaCzstSGqR1hEDtsGibu6JqUofEI/0sY=
ariga.io/atlas v0.15.0/go.mod h1:isZrlzJ5cpoCoKFoY9knZug7Lq4pP1cm8g3XciLZ0Pw=
entgo.io/ent v0.12.5 h1:KREM5E4CSoej4zeGa88Ou/gfturAnpUv0mzAjch1sj4=
entgo.io/ent v0.12.5/go.mod h1:Y3JVAjtlIk8xVZYSn3t3mf8xlZIn5SAOXZQxD6kKI+Q=
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM=
Expand Down Expand Up @@ -154,6 +156,8 @@ github.com/nekomeowww/timecapsule/v2 v2.2.0 h1:5hdcoq7uyIdQCs9ufIg1yuDnfhzsk1bb0
github.com/nekomeowww/timecapsule/v2 v2.2.0/go.mod h1:1rr05h26cZmOaNUw/tSByKfPdomx0Fw9tWxlu+4HQlU=
github.com/nekomeowww/xo v1.3.0 h1:9HmI4enlu3TiBuFeT4NKAOJW0FQCjsp6R9qLk6u6iu8=
github.com/nekomeowww/xo v1.3.0/go.mod h1:vw5BQ33eEpNO2ZwlIO2xnP25mvU2LAfT3CojIcZ+YHg=
github.com/nicksnyder/go-i18n/v2 v2.4.0 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM=
github.com/nicksnyder/go-i18n/v2 v2.4.0/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo/v2 v2.13.2 h1:Bi2gGVkfn6gQcjNjZJVO8Gf0FHzMPf2phUei9tejVMs=
Expand Down Expand Up @@ -308,6 +312,8 @@ google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
2 changes: 1 addition & 1 deletion internal/bots/telegram/handlers/recap/command_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ func newSubscribeRecapCommandWhenUserBlockedMessage(bot *tgbot.Bot, hashKey stri
"", bot.Self.UserName, bot.Self.UserName, hashKey)
}

func (h *CommandHandler) handleUserNeverStartedChatOrBlockedErr(c *tgbot.Context, chatID int64, chatTitle string, message string) (tgbot.Response, error) {
func (h *CommandHandler) handleUserNeverStartedChatOrBlockedErr(c *tgbot.Context, chatID int64, _ string, message string) (tgbot.Response, error) {
msg := tgbotapi.NewMessage(chatID, message)
msg.ReplyToMessageID = c.Update.Message.MessageID
msg.ParseMode = tgbotapi.ModeHTML
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func checkBotIsAdmin(ctx *tgbot.Context) error {
return nil
}

func checkToggle(ctx *tgbot.Context, chatID int64, user *tgbotapi.User) error {
func checkToggle(ctx *tgbot.Context, _ int64, user *tgbotapi.User) error {
err := checkBotIsAdmin(ctx)
if err != nil {
return err
Expand All @@ -61,7 +61,7 @@ func checkToggle(ctx *tgbot.Context, chatID int64, user *tgbotapi.User) error {
return nil
}

func checkAssignMode(ctx *tgbot.Context, chatID int64, user *tgbotapi.User) error {
func checkAssignMode(ctx *tgbot.Context, _ int64, user *tgbotapi.User) error {
err := checkBotIsAdmin(ctx)
if err != nil {
return err
Expand Down
48 changes: 42 additions & 6 deletions internal/bots/telegram/handlers/recap/recap.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,48 @@ func NewHandlers() func(NewHandlersParams) *Handlers {

func (h *Handlers) Install(dispatcher *tgbot.Dispatcher) {
dispatcher.OnCommandGroup("聊天回顾", []tgbot.Command{
{Command: "recap", HelpMessage: "总结过去的聊天记录并生成回顾快报", Handler: tgbot.NewHandler(h.command.handleRecapCommand)},
{Command: "configure_recap", HelpMessage: "配置聊天记录回顾(需要管理权限,<b>请在配置的时候尽量避免使用匿名用户身份或者其他群组的身份进行配置,可能会导致权限检查异常而配置失败。</b>)", Handler: tgbot.NewHandler(h.command.handleConfigureRecapCommand)},
{Command: "recap_forwarded_start", HelpMessage: "使 Bot 接收在私聊中转发给 Bot 的消息,并在发送 /recap_forwarded 后开始总结", Handler: tgbot.NewHandler(h.command.handleRecapForwardedStartCommand)},
{Command: "recap_forwarded", HelpMessage: "使 Bot 停止接收在私聊中转发给 Bot 的消息,对已经转发过的消息进行总结", Handler: tgbot.NewHandler(h.command.handleRecapForwardedCommand)},
{Command: "subscribe_recap", HelpMessage: "订阅当前群组的定时聊天回顾", Handler: tgbot.NewHandler(h.command.handleSubscribeRecapCommand)},
{Command: "unsubscribe_recap", HelpMessage: "取消订阅当前群组的定时聊天回顾", Handler: tgbot.NewHandler(h.command.handleUnsubscribeRecapCommand)},
{
Command: "recap",
Handler: tgbot.NewHandler(h.command.handleRecapCommand),
HelpMessage: func(c *tgbot.Context) string {
return "总结过去的聊天记录并生成回顾快报"
},
},
{
Command: "configure_recap",
Handler: tgbot.NewHandler(h.command.handleConfigureRecapCommand),
HelpMessage: func(c *tgbot.Context) string {
return "配置聊天记录回顾(需要管理权限,<b>请在配置的时候尽量避免使用匿名用户身份或者其他群组的身份进行配置,可能会导致权限检查异常而配置失败。</b>)"
},
},
{
Command: "recap_forwarded_start",
Handler: tgbot.NewHandler(h.command.handleRecapForwardedStartCommand),
HelpMessage: func(c *tgbot.Context) string {
return "使 Bot 接收在私聊中转发给 Bot 的消息,并在发送 /recap_forwarded 后开始总结"
},
},
{
Command: "recap_forwarded",
Handler: tgbot.NewHandler(h.command.handleRecapForwardedCommand),
HelpMessage: func(c *tgbot.Context) string {
return "使 Bot 停止接收在私聊中转发给 Bot 的消息,对已经转发过的消息进行总结"
},
},
{
Command: "subscribe_recap",
Handler: tgbot.NewHandler(h.command.handleSubscribeRecapCommand),
HelpMessage: func(c *tgbot.Context) string {
return "订阅当前群组的定时聊天回顾"
},
},
{
Command: "unsubscribe_recap",
Handler: tgbot.NewHandler(h.command.handleUnsubscribeRecapCommand),
HelpMessage: func(c *tgbot.Context) string {
return "取消订阅当前群组的定时聊天回顾"
},
},
})

dispatcher.OnCancelCommand(h.command.handleRecapForwardedStartShouleCancel, tgbot.NewHandler(h.command.handleRecapForwardedStartCancelCommand))
Expand Down
8 changes: 7 additions & 1 deletion internal/bots/telegram/handlers/summarize/summarize.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,13 @@ func NewHandlers() func(NewHandlersParams) *Handlers {

func (h *Handlers) Install(dispatcher *tgbot.Dispatcher) {
dispatcher.OnCommandGroup("量子速读", []tgbot.Command{
{Command: "smr", HelpMessage: "量子速读网页文章(也支持在频道中使用) 用法:/smr <code>&lt;链接&gt;</code>", Handler: tgbot.NewHandler(h.Handle)},
{
Command: "smr",
Handler: tgbot.NewHandler(h.Handle),
HelpMessage: func(c *tgbot.Context) string {
return "量子速读网页文章(也支持在频道中使用) 用法:/smr <code>&lt;链接&gt;</code>"
},
},
})

dispatcher.OnChannelPost(tgbot.NewHandler(h.HandleChannelPost))
Expand Down
8 changes: 7 additions & 1 deletion internal/configs/configs.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strconv"

"github.com/joho/godotenv"
"github.com/nekomeowww/xo"
"github.com/samber/lo"
goopenai "github.com/sashabaranov/go-openai"
)
Expand Down Expand Up @@ -53,6 +54,8 @@ const (

EnvHardLimitManualRecapRatePerSeconds = "HARD_LIMIT_MANUAL_RECAP_RATE_PER_SECONDS"
EnvHardLimitSummarizeWebpageRatePerSeconds = "HARD_LIMIT_SMR_WEBPAGE_RATE_PER_SECONDS"

EnvLocalesDir = "LOCALES_DIR"
)

type SectionPineconeIndexes struct {
Expand Down Expand Up @@ -125,6 +128,7 @@ type Config struct {
LogLevel string
LogFilePath string
HardLimit SectionHardLimit
LocalesDir string
}

func NewConfig() func() (*Config, error) {
Expand Down Expand Up @@ -250,6 +254,7 @@ func NewConfig() func() (*Config, error) {
ManualRecapRatePerSeconds: manualRecapRatePerSecondsHardLimit,
SummarizeWebpageRatePerSeconds: summarizeWebpageRatePerSecondsHardLimit,
},
LocalesDir: getEnv(EnvLocalesDir),
}, nil
}
}
Expand All @@ -270,7 +275,8 @@ func NewTestConfig() func() *Config {
TLSEnabled: false,
ClientCacheEnabled: false,
},
LogLevel: "debug",
LogLevel: "debug",
LocalesDir: xo.RelativePathOf("../locales"),
}
}
}
25 changes: 25 additions & 0 deletions internal/lib/i18n.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package lib

import (
"go.uber.org/fx"

"github.com/nekomeowww/insights-bot/internal/configs"
"github.com/nekomeowww/insights-bot/pkg/i18n"
"github.com/nekomeowww/insights-bot/pkg/logger"
)

type NewI18nParams struct {
fx.In

Configs *configs.Config
Logger *logger.Logger
}

func NewI18n() func(NewI18nParams) (*i18n.I18n, error) {
return func(params NewI18nParams) (*i18n.I18n, error) {
return i18n.NewI18n(
i18n.WithLocalesDir(params.Configs.LocalesDir),
i18n.WithLogger(params.Logger),
)
}
}
1 change: 1 addition & 0 deletions internal/lib/lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ import "go.uber.org/fx"
func NewModules() fx.Option {
return fx.Options(
fx.Provide(NewLogger()),
fx.Provide(NewI18n()),
)
}
2 changes: 1 addition & 1 deletion internal/models/chathistories/chat_histories_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func TestExtractTextFromMessage(t *testing.T) {
}, nil
}

expect := "看看这些链接:[Documentation](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/stringsandcharacters/#Extended-Grapheme-Clusters) 、[GPT-4 Developer Livestream - YouTube](https://www.youtube.com/watch?v=outcGtbnMuQ) [GitHub - nekomeowww/insights-bot: A bot works with OpenAI GPT models to provide insights for your info flows.](https://github.com/nekomeowww/insights-bot) 还有 [这个](https://matters.town/@1435Club/322889-这几天-web3在大理发生了什么),和这个 [Google for Developers Europe (@GoogleDevEurope) on X](https://twitter.com/GoogleDevEurope/status/1640667303158198272)"
expect := "看看这些链接:[Documentation](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/stringsandcharacters/#Extended-Grapheme-Clusters) 、[GPT-4 Developer Livestream - YouTube](https://www.youtube.com/watch?v=outcGtbnMuQ) [GitHub - nekomeowww/insights-bot: A bot works with OpenAI GPT models to provide insights for your info flows.](https://github.com/nekomeowww/insights-bot) 还有 [这个](https://matters.town/@1435Club/322889-这几天-web3在大理发生了什么),和这个 https://twitter.com/GoogleDevEurope/status/1640667303158198272"
assert.Equal(expect, model.ExtractTextFromMessage(message))
})
}
Expand Down
15 changes: 15 additions & 0 deletions locales/en.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
system:
commands:
start:
help: Start interacting with the bot
help:
help: Get help
message: |
Hi! 👋 Welcome using Insights Bot!
I currently support these commands:
{{ .Commands }}
cancel:
help: Cancel the current activated operation
alreadyCancelledAll: There is no activated operation to cancel
15 changes: 15 additions & 0 deletions locales/zh-CN.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
system:
commands:
start:
help: 开始与 Bot 的交互
help:
help: 获取帮助
message: |
你好!👋 欢迎使用 Insights Bot!
我当前支持这些命令:
{{ .Commands }}
cancel:
help: 取消当前操作
alreadyCancelledAll: 已经没有正在进行的操作了
6 changes: 3 additions & 3 deletions pkg/bots/tgbot/cancel_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ func (h *cancelCommandHandler) Command() string {
return "cancel"
}

func (h *cancelCommandHandler) CommandHelp() string {
return "取消正在进行的操作"
func (h *cancelCommandHandler) CommandHelp(c *Context) string {
return c.T("system.commands.cancel.help")
}

func (h *cancelCommandHandler) handle(c *Context) (Response, error) {
Expand Down Expand Up @@ -59,5 +59,5 @@ func (h *cancelCommandHandler) handle(c *Context) (Response, error) {
return nil, err
}

return c.NewMessageReplyTo("已经没有正在进行的操作了", c.Update.Message.MessageID), nil
return c.NewMessageReplyTo(c.T("system.commands.cancel.alreadyCancelledAll"), c.Update.Message.MessageID), nil
}
27 changes: 26 additions & 1 deletion pkg/bots/tgbot/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import (
"time"

tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
"github.com/nekomeowww/insights-bot/pkg/i18n"
"github.com/nekomeowww/insights-bot/pkg/logger"
"github.com/nekomeowww/insights-bot/pkg/types/telegram"
"github.com/redis/rueidis"
"go.uber.org/zap"
)

type UpdateType string
Expand Down Expand Up @@ -41,6 +43,7 @@ type Context struct {
Bot *Bot
Update tgbotapi.Update
Logger *logger.Logger
I18n *i18n.I18n

mutex sync.Mutex
rueidisClient rueidis.Client
Expand All @@ -55,11 +58,12 @@ type Context struct {
callbackQueryHandlerActionDataIsEmpty bool
}

func NewContext(bot *tgbotapi.BotAPI, update tgbotapi.Update, logger *logger.Logger, rueidisClient rueidis.Client) *Context {
func NewContext(bot *tgbotapi.BotAPI, update tgbotapi.Update, logger *logger.Logger, i18n *i18n.I18n, rueidisClient rueidis.Client) *Context {
return &Context{
Bot: &Bot{BotAPI: bot, logger: logger, rueidisClient: rueidisClient},
Update: update,
Logger: logger,
I18n: i18n,
rueidisClient: rueidisClient,
isCallbackQuery: false,
callbackQueryHandlerRoute: "",
Expand Down Expand Up @@ -130,6 +134,27 @@ func (c *Context) IsAborted() bool {
return c.abort
}

func (c *Context) T(key string, args ...any) string {
return c.I18n.TWithLanguage(c.Language(), key, args...)
}

func (c *Context) Language() string {
if c.Update.SentFrom() == nil {
c.Logger.Warn("update.SentFrom() is nil, fallback to 'en' language.")
return "en"
}

languageCode := c.Update.SentFrom().LanguageCode
if languageCode == "" {
c.Logger.Warn("update.SentFrom().LanguageCode is empty, fallback to 'en' language.")
return "en"
}

c.Logger.Debug("resolved language code", zap.String("languageCode", languageCode))

return languageCode
}

func (c *Context) initForCallbackQuery(route, routeHash, actionDataHash string) {
c.mutex.Lock()
defer c.mutex.Unlock()
Expand Down
Loading

0 comments on commit b6e3e0c

Please sign in to comment.