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

Add source push flags #195

Merged
merged 3 commits into from
Jul 17, 2023
Merged
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
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,15 @@ fall back to taking the filesystem timestamp into account.
any time.
- `--silent`: Reduce verbosity of the output.

- `--replace-edited-strings`: If present, source strings that have been edited
(in the editor UI or via the API) will not be protected from this source
file push and will instead be replaced. This can also be set on a
per-resource level in the configuration file.

- `--keep-transations`: If present, translations of source strings with the
same key whose content changes will not be discarded. This can also be set on
a per-resource level in the configuration file.

### Pulling Files from Transifex

`tx pull` is used to pull language files (usually translation language files) from
Expand Down
38 changes: 25 additions & 13 deletions cmd/tx/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,16 @@ func Main() {
Name: "silent",
Usage: "Whether to reduce verbosity of the output",
},
&cli.BoolFlag{
Name: "replace-edited-strings",
Usage: "Whether to replace source strings that have been edited in the " +
"meantime",
},
&cli.BoolFlag{
Name: "keep-translations",
Usage: "Whether to not discard translations if a source string with a " +
"pre-existing key changes",
},
},
Action: func(c *cli.Context) error {
cfg, err := config.LoadFromPaths(
Expand Down Expand Up @@ -327,19 +337,21 @@ func Main() {
}

args := txlib.PushCommandArguments{
Source: c.Bool("source"),
Translation: c.Bool("translation"),
Force: c.Bool("force"),
Skip: c.Bool("skip"),
Xliff: c.Bool("xliff"),
Languages: languages,
ResourceIds: resourceIds,
UseGitTimestamps: c.Bool("use-git-timestamps"),
Branch: c.String("branch"),
Base: c.String("base"),
All: c.Bool("all"),
Workers: workers,
Silent: c.Bool("silent"),
Source: c.Bool("source"),
Translation: c.Bool("translation"),
Force: c.Bool("force"),
Skip: c.Bool("skip"),
Xliff: c.Bool("xliff"),
Languages: languages,
ResourceIds: resourceIds,
UseGitTimestamps: c.Bool("use-git-timestamps"),
Branch: c.String("branch"),
Base: c.String("base"),
All: c.Bool("all"),
Workers: workers,
Silent: c.Bool("silent"),
ReplaceEditedStrings: c.Bool("replace-edited-strings"),
KeepTranslations: c.Bool("keep-translations"),
}

if args.All && len(args.Languages) > 0 {
Expand Down
80 changes: 58 additions & 22 deletions internal/txlib/config/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,19 @@ type LocalConfig struct {
}

type Resource struct {
OrganizationSlug string
ProjectSlug string
ResourceSlug string
FileFilter string
SourceFile string
SourceLanguage string
Type string
LanguageMappings map[string]string
Overrides map[string]string
MinimumPercentage int
ResourceName string
OrganizationSlug string
ProjectSlug string
ResourceSlug string
FileFilter string
SourceFile string
SourceLanguage string
Type string
LanguageMappings map[string]string
Overrides map[string]string
MinimumPercentage int
ResourceName string
ReplaceEditedStrings bool
KeepTranslations bool
}

func loadLocalConfig() (*LocalConfig, error) {
Expand Down Expand Up @@ -121,18 +123,40 @@ func loadLocalConfigFromBytes(data []byte) (*LocalConfig, error) {
return nil, err
}

replaceEditedStrings := false
if section.HasKey("replace_edited_strings") {
replaceEditedStrings, err = section.Key("replace_edited_strings").Bool()
if err != nil {
return nil, fmt.Errorf(
"'replace_edited_strings' needs to be 'true' or 'false': %s", err,
)
}
}

keepTranslations := false
if section.HasKey("keep_translations") {
keepTranslations, err = section.Key("keep_translations").Bool()
if err != nil {
return nil, fmt.Errorf(
"'keep_translations' needs to be 'true' or 'false': %s", err,
)
}
}

resource := Resource{
OrganizationSlug: organizationSlug,
ProjectSlug: projectSlug,
ResourceSlug: resourceSlug,
FileFilter: section.Key("file_filter").String(),
SourceFile: section.Key("source_file").String(),
SourceLanguage: section.Key("source_lang").String(),
Type: section.Key("type").String(),
LanguageMappings: make(map[string]string),
Overrides: make(map[string]string),
MinimumPercentage: -1,
ResourceName: section.Key("resource_name").String(),
OrganizationSlug: organizationSlug,
ProjectSlug: projectSlug,
ResourceSlug: resourceSlug,
FileFilter: section.Key("file_filter").String(),
SourceFile: section.Key("source_file").String(),
SourceLanguage: section.Key("source_lang").String(),
Type: section.Key("type").String(),
LanguageMappings: make(map[string]string),
Overrides: make(map[string]string),
MinimumPercentage: -1,
ResourceName: section.Key("resource_name").String(),
ReplaceEditedStrings: replaceEditedStrings,
KeepTranslations: keepTranslations,
}

// Get first the perc in string to check if exists because .Key returns
Expand Down Expand Up @@ -282,6 +306,14 @@ func (localCfg LocalConfig) saveToWriter(file io.Writer) error {
return err
}
}

section.NewKey(
"replace_edited_strings", strconv.FormatBool(resource.ReplaceEditedStrings),
)

section.NewKey(
"keep_translations", strconv.FormatBool(resource.KeepTranslations),
)
}

_, err = cfg.WriteTo(file)
Expand Down Expand Up @@ -366,6 +398,10 @@ func localConfigsEqual(left, right *LocalConfig) bool {
return false
}
}

if leftResource.ReplaceEditedStrings != rightResource.ReplaceEditedStrings {
return false
}
}

return true
Expand Down
15 changes: 11 additions & 4 deletions internal/txlib/migrate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"log"
"os"
"path/filepath"
"regexp"
"strings"
"testing"

Expand Down Expand Up @@ -680,10 +681,16 @@ func TestResourceMigrationFailed(t *testing.T) {
string(content), "projslug1.ares"))
assert.True(t, strings.Contains(
string(content), "o:org:p:projslug2:r:ares2"))
assert.True(t, strings.Contains(
string(content), "minimum_perc = 10"))
assert.True(t, strings.Contains(
string(content), "minimum_perc = 0"))
matched, err := regexp.MatchString(`minimum_perc\s*=\s*10`, string(content))
if err != nil {
t.Error(err)
}
assert.True(t, matched)
matched, err = regexp.MatchString(`minimum_perc\s*=\s*0`, string(content))
if err != nil {
t.Error(err)
}
assert.True(t, matched)
}

func TestBackUpFileCreated(t *testing.T) {
Expand Down
50 changes: 30 additions & 20 deletions internal/txlib/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,21 @@ import (
)

type PushCommandArguments struct {
Source bool
Translation bool
Force bool
Skip bool
Xliff bool
Languages []string
ResourceIds []string
UseGitTimestamps bool
Branch string
Base string
All bool
Workers int
Silent bool
Source bool
Translation bool
Force bool
Skip bool
Xliff bool
Languages []string
ResourceIds []string
UseGitTimestamps bool
Branch string
Base string
All bool
Workers int
Silent bool
ReplaceEditedStrings bool
KeepTranslations bool
}

func PushCommand(
Expand Down Expand Up @@ -445,6 +447,8 @@ func (task *ResourcePushTask) Run(send func(string), abort func()) {
remoteStats[sourceLanguage.Id],
args,
resourceIsNew,
args.ReplaceEditedStrings || cfgResource.ReplaceEditedStrings,
args.KeepTranslations || cfgResource.KeepTranslations,
}
}
if args.Translation { // -t flag is set
Expand Down Expand Up @@ -565,12 +569,14 @@ func (task *LanguagePushTask) Run(send func(string), abort func()) {
}

type SourceFilePushTask struct {
api *jsonapi.Connection
resource *jsonapi.Resource
sourceFile string
remoteStats *jsonapi.Resource
args PushCommandArguments
resourceIsNew bool
api *jsonapi.Connection
resource *jsonapi.Resource
sourceFile string
remoteStats *jsonapi.Resource
args PushCommandArguments
resourceIsNew bool
replaceEditedStrings bool
keepTranslations bool
}

func (task *SourceFilePushTask) Run(send func(string), abort func()) {
Expand All @@ -580,6 +586,8 @@ func (task *SourceFilePushTask) Run(send func(string), abort func()) {
remoteStats := task.remoteStats
args := task.args
resourceIsNew := task.resourceIsNew
replaceEditedStrings := task.replaceEditedStrings
keepTranslations := task.keepTranslations

parts := strings.Split(resource.Id, ":")
sendMessage := func(body string, force bool) {
Expand Down Expand Up @@ -624,7 +632,9 @@ func (task *SourceFilePushTask) Run(send func(string), abort func()) {
err = handleThrottling(
func() error {
var err error
sourceUpload, err = txapi.UploadSource(api, resource, file)
sourceUpload, err = txapi.UploadSource(
api, resource, file, replaceEditedStrings, keepTranslations,
)
return err
},
"Uploading file",
Expand Down
6 changes: 6 additions & 0 deletions pkg/jsonapi/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"mime/multipart"
"strconv"
)

type Resource struct {
Expand Down Expand Up @@ -191,6 +192,11 @@ func (r *Resource) SaveAsMultipart(fields []string) error {
if err != nil {
return err
}
case bool:
err := writer.WriteField(field, strconv.FormatBool(data))
if err != nil {
return err
}
case []byte:
w, err := writer.CreateFormFile(field,
fmt.Sprintf("%s.txt", field))
Expand Down
10 changes: 8 additions & 2 deletions pkg/txapi/resource_strings_async_uploads.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ func (err *ResourceStringAsyncUploadAttributes) Error() string {
}

func UploadSource(
api *jsonapi.Connection, resource *jsonapi.Resource, file io.Reader,
api *jsonapi.Connection,
resource *jsonapi.Resource,
file io.Reader,
replaceEditedStrings bool,
keepTranslations bool,
) (*jsonapi.Resource, error) {
data, err := io.ReadAll(file)
if err != nil {
Expand All @@ -49,7 +53,9 @@ func UploadSource(
// Setting attributes directly here because POST and GET attributes are
// different
Attributes: map[string]interface{}{
"content": data,
"content": data,
"replace_edited_strings": replaceEditedStrings,
"keep_translations": keepTranslations,
},
}
upload.SetRelated("resource", resource)
Expand Down