Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Base setup for i18n for server with go-i18n library #782

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions assets/i18n/active.en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"github.command.help.title": "###### Mattermost GitHub Plugin - Slash Command Help\n"
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require (
github.com/gorilla/mux v1.8.1
github.com/mattermost/mattermost/server/public v0.0.15
github.com/microcosm-cc/bluemonday v1.0.19
github.com/nicksnyder/go-i18n/v2 v2.4.0
github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.8.4
golang.org/x/oauth2 v0.17.0
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
Expand Down Expand Up @@ -154,6 +156,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
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/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
Expand Down
13 changes: 11 additions & 2 deletions server/plugin/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/plugin"
"github.com/mattermost/mattermost/server/public/pluginapi/experimental/command"
"github.com/nicksnyder/go-i18n/v2/i18n"
)

const (
Expand Down Expand Up @@ -609,14 +610,22 @@ func (p *Plugin) handleMe(_ *plugin.Context, _ *model.CommandArgs, _ []string, u
return text
}

func (p *Plugin) handleHelp(_ *plugin.Context, _ *model.CommandArgs, _ []string, _ *GitHubUserInfo) string {
func (p *Plugin) handleHelp(_ *plugin.Context, args *model.CommandArgs, _ []string, _ *GitHubUserInfo) string {
l := p.b.GetUserLocalizer(args.UserId)
message, err := renderTemplate("helpText", p.getConfiguration())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious how we can use the translations in the templates?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah @mickmister I was trying to find the same thing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we expose functions to call from within the template?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is something we should try and solve before merging the PR. Any question marks we have on how to do things like this should ideally be resolved before contributors go and work on the same sort of things

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can implement this method:

func (p *Plugin) localize(id, other string) string {
	return p.b.LocalizeWithConfig(l, &i18n.LocalizeConfig{
		DefaultMessage: &i18n.Message{
			ID:    id,
			Other: other,
		},
	})
}

Then change

to

func (p *Plugin) initTemplates() {

and add a block here

funcMap["commitAuthor"] = func(commit *github.HeadCommit) *github.CommitAuthor {
if showAuthorInCommitNotification {
return commit.GetAuthor()
}
return commit.GetCommitter()
}
masterTemplate = template.Must(template.New("master").Funcs(funcMap).Parse(""))

to

funcMap["i18n"] = p.localize

Then we should be able to use the i18n function in the templates

Copy link
Contributor Author

@Kshitij-Katiyar Kshitij-Katiyar Jun 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @mickmister Thanks for the approach above, I tried a bunch of things as stated above but faced several issues.
First of all, there is a huge lack of documentation and resources on the internet regarding Go's text/template and i was not able to find anything which connects the translation and template together. If you have some resources, please share those i would love to deep dive into those.

First of all, When using higher-order functions inside the template directly, it prints the function returned by the parent function instead of trying to run the child function returned with the arguments passed(similar code here dummy code). I also tried storing the child function in a variable and calling it with the arguments, but that didn't work either. (You can have a link here goPlayground)

Secondly, the approach of making the initTemplate a method of the Plugin also didn't work because, during the initialization of the template, the Plugin is null.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Secondly, the approach of making the initTemplate a method of the Plugin also didn't work because, during the initialization of the template, the Plugin is null.

@Kshitij-Katiyar We should be able to call initTemplate during OnActivate to make that work

I'm not sure about the template functions behavior

if err != nil {
p.client.Log.Warn("Failed to render help template", "error", err.Error())
return "Encountered an error posting help text."
}

return "###### Mattermost GitHub Plugin - Slash Command Help\n" + message
helpTitle := p.b.LocalizeWithConfig(l, &i18n.LocalizeConfig{
DefaultMessage: &i18n.Message{
ID: "github.command.help.title",
Other: "###### Mattermost GitHub Plugin - Slash Command help\n",
},
})

return helpTitle + message
}

func (p *Plugin) handleSettings(_ *plugin.Context, _ *model.CommandArgs, parameters []string, userInfo *GitHubUserInfo) string {
Expand Down
9 changes: 9 additions & 0 deletions server/plugin/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/mattermost/mattermost/server/public/pluginapi/experimental/bot/logger"
"github.com/mattermost/mattermost/server/public/pluginapi/experimental/bot/poster"
"github.com/mattermost/mattermost/server/public/pluginapi/experimental/telemetry"
"github.com/mattermost/mattermost/server/public/pluginapi/i18n"

"github.com/mattermost/mattermost-plugin-github/server/plugin/graphql"
)
Expand Down Expand Up @@ -95,6 +96,8 @@ type Plugin struct {
poster poster.Poster
flowManager *FlowManager

b *i18n.Bundle
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This names seems a bit cryptic to me. Maybe we can call it localization or i18n? @hanzei Thoughts on this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, b isn't quite telling. 2./5 on bundle as i18n is already a library name.


CommandHandlers map[string]CommandHandleFunc

// githubPermalinkRegex is used to parse github permalinks in post messages.
Expand Down Expand Up @@ -267,6 +270,12 @@ func (p *Plugin) OnActivate() error {
p.webhookBroker = NewWebhookBroker(p.sendGitHubPingEvent)
p.oauthBroker = NewOAuthBroker(p.sendOAuthCompleteEvent)

i18nBundle, err := i18n.InitBundle(p.API, filepath.Join("assets", "i18n"))
if err != nil {
return err
}
p.b = i18nBundle

botID, err := p.client.Bot.EnsureBot(&model.Bot{
OwnerId: Manifest.Id, // Workaround to support older server version affected by https://github.com/mattermost/mattermost-server/pull/21560
Username: "github",
Expand Down
Loading