Skip to content

Commit 05c3163

Browse files
author
Konstantinos Bairaktaris
authored
Merge pull request #195 from transifex/GLUON-254_add_source_push_flags
Add source push flags
2 parents 4e20586 + 26736f8 commit 05c3163

File tree

7 files changed

+147
-61
lines changed

7 files changed

+147
-61
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,15 @@ fall back to taking the filesystem timestamp into account.
590590
any time.
591591
- `--silent`: Reduce verbosity of the output.
592592
593+
- `--replace-edited-strings`: If present, source strings that have been edited
594+
(in the editor UI or via the API) will not be protected from this source
595+
file push and will instead be replaced. This can also be set on a
596+
per-resource level in the configuration file.
597+
598+
- `--keep-transations`: If present, translations of source strings with the
599+
same key whose content changes will not be discarded. This can also be set on
600+
a per-resource level in the configuration file.
601+
593602
### Pulling Files from Transifex
594603
595604
`tx pull` is used to pull language files (usually translation language files) from

cmd/tx/main.go

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,16 @@ func Main() {
259259
Name: "silent",
260260
Usage: "Whether to reduce verbosity of the output",
261261
},
262+
&cli.BoolFlag{
263+
Name: "replace-edited-strings",
264+
Usage: "Whether to replace source strings that have been edited in the " +
265+
"meantime",
266+
},
267+
&cli.BoolFlag{
268+
Name: "keep-translations",
269+
Usage: "Whether to not discard translations if a source string with a " +
270+
"pre-existing key changes",
271+
},
262272
},
263273
Action: func(c *cli.Context) error {
264274
cfg, err := config.LoadFromPaths(
@@ -327,19 +337,21 @@ func Main() {
327337
}
328338

329339
args := txlib.PushCommandArguments{
330-
Source: c.Bool("source"),
331-
Translation: c.Bool("translation"),
332-
Force: c.Bool("force"),
333-
Skip: c.Bool("skip"),
334-
Xliff: c.Bool("xliff"),
335-
Languages: languages,
336-
ResourceIds: resourceIds,
337-
UseGitTimestamps: c.Bool("use-git-timestamps"),
338-
Branch: c.String("branch"),
339-
Base: c.String("base"),
340-
All: c.Bool("all"),
341-
Workers: workers,
342-
Silent: c.Bool("silent"),
340+
Source: c.Bool("source"),
341+
Translation: c.Bool("translation"),
342+
Force: c.Bool("force"),
343+
Skip: c.Bool("skip"),
344+
Xliff: c.Bool("xliff"),
345+
Languages: languages,
346+
ResourceIds: resourceIds,
347+
UseGitTimestamps: c.Bool("use-git-timestamps"),
348+
Branch: c.String("branch"),
349+
Base: c.String("base"),
350+
All: c.Bool("all"),
351+
Workers: workers,
352+
Silent: c.Bool("silent"),
353+
ReplaceEditedStrings: c.Bool("replace-edited-strings"),
354+
KeepTranslations: c.Bool("keep-translations"),
343355
}
344356

345357
if args.All && len(args.Languages) > 0 {

internal/txlib/config/local.go

Lines changed: 58 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,19 @@ type LocalConfig struct {
2121
}
2222

2323
type Resource struct {
24-
OrganizationSlug string
25-
ProjectSlug string
26-
ResourceSlug string
27-
FileFilter string
28-
SourceFile string
29-
SourceLanguage string
30-
Type string
31-
LanguageMappings map[string]string
32-
Overrides map[string]string
33-
MinimumPercentage int
34-
ResourceName string
24+
OrganizationSlug string
25+
ProjectSlug string
26+
ResourceSlug string
27+
FileFilter string
28+
SourceFile string
29+
SourceLanguage string
30+
Type string
31+
LanguageMappings map[string]string
32+
Overrides map[string]string
33+
MinimumPercentage int
34+
ResourceName string
35+
ReplaceEditedStrings bool
36+
KeepTranslations bool
3537
}
3638

3739
func loadLocalConfig() (*LocalConfig, error) {
@@ -121,18 +123,40 @@ func loadLocalConfigFromBytes(data []byte) (*LocalConfig, error) {
121123
return nil, err
122124
}
123125

126+
replaceEditedStrings := false
127+
if section.HasKey("replace_edited_strings") {
128+
replaceEditedStrings, err = section.Key("replace_edited_strings").Bool()
129+
if err != nil {
130+
return nil, fmt.Errorf(
131+
"'replace_edited_strings' needs to be 'true' or 'false': %s", err,
132+
)
133+
}
134+
}
135+
136+
keepTranslations := false
137+
if section.HasKey("keep_translations") {
138+
keepTranslations, err = section.Key("keep_translations").Bool()
139+
if err != nil {
140+
return nil, fmt.Errorf(
141+
"'keep_translations' needs to be 'true' or 'false': %s", err,
142+
)
143+
}
144+
}
145+
124146
resource := Resource{
125-
OrganizationSlug: organizationSlug,
126-
ProjectSlug: projectSlug,
127-
ResourceSlug: resourceSlug,
128-
FileFilter: section.Key("file_filter").String(),
129-
SourceFile: section.Key("source_file").String(),
130-
SourceLanguage: section.Key("source_lang").String(),
131-
Type: section.Key("type").String(),
132-
LanguageMappings: make(map[string]string),
133-
Overrides: make(map[string]string),
134-
MinimumPercentage: -1,
135-
ResourceName: section.Key("resource_name").String(),
147+
OrganizationSlug: organizationSlug,
148+
ProjectSlug: projectSlug,
149+
ResourceSlug: resourceSlug,
150+
FileFilter: section.Key("file_filter").String(),
151+
SourceFile: section.Key("source_file").String(),
152+
SourceLanguage: section.Key("source_lang").String(),
153+
Type: section.Key("type").String(),
154+
LanguageMappings: make(map[string]string),
155+
Overrides: make(map[string]string),
156+
MinimumPercentage: -1,
157+
ResourceName: section.Key("resource_name").String(),
158+
ReplaceEditedStrings: replaceEditedStrings,
159+
KeepTranslations: keepTranslations,
136160
}
137161

138162
// Get first the perc in string to check if exists because .Key returns
@@ -282,6 +306,14 @@ func (localCfg LocalConfig) saveToWriter(file io.Writer) error {
282306
return err
283307
}
284308
}
309+
310+
section.NewKey(
311+
"replace_edited_strings", strconv.FormatBool(resource.ReplaceEditedStrings),
312+
)
313+
314+
section.NewKey(
315+
"keep_translations", strconv.FormatBool(resource.KeepTranslations),
316+
)
285317
}
286318

287319
_, err = cfg.WriteTo(file)
@@ -366,6 +398,10 @@ func localConfigsEqual(left, right *LocalConfig) bool {
366398
return false
367399
}
368400
}
401+
402+
if leftResource.ReplaceEditedStrings != rightResource.ReplaceEditedStrings {
403+
return false
404+
}
369405
}
370406

371407
return true

internal/txlib/migrate_test.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"log"
77
"os"
88
"path/filepath"
9+
"regexp"
910
"strings"
1011
"testing"
1112

@@ -680,10 +681,16 @@ func TestResourceMigrationFailed(t *testing.T) {
680681
string(content), "projslug1.ares"))
681682
assert.True(t, strings.Contains(
682683
string(content), "o:org:p:projslug2:r:ares2"))
683-
assert.True(t, strings.Contains(
684-
string(content), "minimum_perc = 10"))
685-
assert.True(t, strings.Contains(
686-
string(content), "minimum_perc = 0"))
684+
matched, err := regexp.MatchString(`minimum_perc\s*=\s*10`, string(content))
685+
if err != nil {
686+
t.Error(err)
687+
}
688+
assert.True(t, matched)
689+
matched, err = regexp.MatchString(`minimum_perc\s*=\s*0`, string(content))
690+
if err != nil {
691+
t.Error(err)
692+
}
693+
assert.True(t, matched)
687694
}
688695

689696
func TestBackUpFileCreated(t *testing.T) {

internal/txlib/push.go

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,21 @@ import (
1717
)
1818

1919
type PushCommandArguments struct {
20-
Source bool
21-
Translation bool
22-
Force bool
23-
Skip bool
24-
Xliff bool
25-
Languages []string
26-
ResourceIds []string
27-
UseGitTimestamps bool
28-
Branch string
29-
Base string
30-
All bool
31-
Workers int
32-
Silent bool
20+
Source bool
21+
Translation bool
22+
Force bool
23+
Skip bool
24+
Xliff bool
25+
Languages []string
26+
ResourceIds []string
27+
UseGitTimestamps bool
28+
Branch string
29+
Base string
30+
All bool
31+
Workers int
32+
Silent bool
33+
ReplaceEditedStrings bool
34+
KeepTranslations bool
3335
}
3436

3537
func PushCommand(
@@ -445,6 +447,8 @@ func (task *ResourcePushTask) Run(send func(string), abort func()) {
445447
remoteStats[sourceLanguage.Id],
446448
args,
447449
resourceIsNew,
450+
args.ReplaceEditedStrings || cfgResource.ReplaceEditedStrings,
451+
args.KeepTranslations || cfgResource.KeepTranslations,
448452
}
449453
}
450454
if args.Translation { // -t flag is set
@@ -565,12 +569,14 @@ func (task *LanguagePushTask) Run(send func(string), abort func()) {
565569
}
566570

567571
type SourceFilePushTask struct {
568-
api *jsonapi.Connection
569-
resource *jsonapi.Resource
570-
sourceFile string
571-
remoteStats *jsonapi.Resource
572-
args PushCommandArguments
573-
resourceIsNew bool
572+
api *jsonapi.Connection
573+
resource *jsonapi.Resource
574+
sourceFile string
575+
remoteStats *jsonapi.Resource
576+
args PushCommandArguments
577+
resourceIsNew bool
578+
replaceEditedStrings bool
579+
keepTranslations bool
574580
}
575581

576582
func (task *SourceFilePushTask) Run(send func(string), abort func()) {
@@ -580,6 +586,8 @@ func (task *SourceFilePushTask) Run(send func(string), abort func()) {
580586
remoteStats := task.remoteStats
581587
args := task.args
582588
resourceIsNew := task.resourceIsNew
589+
replaceEditedStrings := task.replaceEditedStrings
590+
keepTranslations := task.keepTranslations
583591

584592
parts := strings.Split(resource.Id, ":")
585593
sendMessage := func(body string, force bool) {
@@ -624,7 +632,9 @@ func (task *SourceFilePushTask) Run(send func(string), abort func()) {
624632
err = handleThrottling(
625633
func() error {
626634
var err error
627-
sourceUpload, err = txapi.UploadSource(api, resource, file)
635+
sourceUpload, err = txapi.UploadSource(
636+
api, resource, file, replaceEditedStrings, keepTranslations,
637+
)
628638
return err
629639
},
630640
"Uploading file",

pkg/jsonapi/resource.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"errors"
77
"fmt"
88
"mime/multipart"
9+
"strconv"
910
)
1011

1112
type Resource struct {
@@ -191,6 +192,11 @@ func (r *Resource) SaveAsMultipart(fields []string) error {
191192
if err != nil {
192193
return err
193194
}
195+
case bool:
196+
err := writer.WriteField(field, strconv.FormatBool(data))
197+
if err != nil {
198+
return err
199+
}
194200
case []byte:
195201
w, err := writer.CreateFormFile(field,
196202
fmt.Sprintf("%s.txt", field))

pkg/txapi/resource_strings_async_uploads.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,11 @@ func (err *ResourceStringAsyncUploadAttributes) Error() string {
3636
}
3737

3838
func UploadSource(
39-
api *jsonapi.Connection, resource *jsonapi.Resource, file io.Reader,
39+
api *jsonapi.Connection,
40+
resource *jsonapi.Resource,
41+
file io.Reader,
42+
replaceEditedStrings bool,
43+
keepTranslations bool,
4044
) (*jsonapi.Resource, error) {
4145
data, err := io.ReadAll(file)
4246
if err != nil {
@@ -49,7 +53,9 @@ func UploadSource(
4953
// Setting attributes directly here because POST and GET attributes are
5054
// different
5155
Attributes: map[string]interface{}{
52-
"content": data,
56+
"content": data,
57+
"replace_edited_strings": replaceEditedStrings,
58+
"keep_translations": keepTranslations,
5359
},
5460
}
5561
upload.SetRelated("resource", resource)

0 commit comments

Comments
 (0)