fastlane-plugin-localize 0.1.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 44a29020ea890b0cd1af66e88acec9b82365c57e3dfffc3c2947bef6d2ff243b
|
4
|
+
data.tar.gz: ed5be6c7cd95fa51aaf26c4f84d3b974ab4e51903984be214302f3d70be965fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 112308493533f28118e0622beac78952c48a65897f637b174e119b3462f9a94ad5d0cb8b17d2d5118a4e47cde633604120a628ac441649e18a5a449525263d12
|
7
|
+
data.tar.gz: 44e950b5735531cc135183e5d1321eabce0c42badbed3589618126e2ed38b8a3d0a9ecce517a4199b4a03e127af235f151eaa97b1507f48f797fe5588dec7991
|
data/README.md
CHANGED
@@ -14,13 +14,38 @@ fastlane add_plugin localize
|
|
14
14
|
|
15
15
|
Searches the code for extractable strings and allows interactive extraction to .strings file.
|
16
16
|
|
17
|
-
|
17
|
+
- Whitelists non-extracted strings for further runs
|
18
|
+
- Extracts as `NSLocalizedString` by default
|
19
|
+
- Support for [Swiftgen](https://github.com/SwiftGen/SwiftGen) by supplying `use_swiftgen:true`
|
18
20
|
|
19
|
-
|
21
|
+

|
20
22
|
|
21
|
-
|
23
|
+
## Run from Commandline
|
22
24
|
|
23
|
-
|
25
|
+
To show all options:
|
26
|
+
|
27
|
+
```bash
|
28
|
+
fastlane action localize
|
29
|
+
```
|
30
|
+
|
31
|
+
Example:
|
32
|
+
|
33
|
+
```bash
|
34
|
+
fastlane run localize strings_file:"Sources/Base/Supporting Files/en.lproj/Localizable.strings" file_filter:"Swiftgen,Sourcery" use_swiftgen:"true"
|
35
|
+
```
|
36
|
+
|
37
|
+
## Run from Fastfile
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
desc "Search for localizable strings"
|
41
|
+
lane :localize_strings do
|
42
|
+
localize(
|
43
|
+
strings_file: "Sources/Base/Supporting Files/en.lproj/Localizable.strings",
|
44
|
+
file_filter: "Swiftgen,Sourcery", # filters files with these words in their path
|
45
|
+
use_swiftgen: "true" # remove to use NSLocalizableString instead
|
46
|
+
)
|
47
|
+
end
|
48
|
+
```
|
24
49
|
|
25
50
|
## Run tests for this plugin
|
26
51
|
|
@@ -1,12 +1,13 @@
|
|
1
|
-
require
|
2
|
-
require_relative
|
1
|
+
require "fastlane/action"
|
2
|
+
require_relative "../helper/localize_helper"
|
3
3
|
|
4
4
|
module Fastlane
|
5
5
|
module Actions
|
6
6
|
class LocalizeAction < Action
|
7
7
|
def self.run(params)
|
8
8
|
project = Helper::LocalizeHelper.getProject(params)
|
9
|
-
|
9
|
+
|
10
|
+
target = Helper::LocalizeHelper.getTarget(params)
|
10
11
|
|
11
12
|
files = Helper::LocalizeHelper.codeFiles(target, params)
|
12
13
|
|
@@ -14,7 +15,6 @@ module Fastlane
|
|
14
15
|
Helper::LocalizeHelper.stringsFromFile(file)
|
15
16
|
end
|
16
17
|
|
17
|
-
|
18
18
|
matchHash = {}
|
19
19
|
|
20
20
|
matches.each do |match|
|
@@ -22,27 +22,29 @@ module Fastlane
|
|
22
22
|
matchHash[match[0]] << match
|
23
23
|
end
|
24
24
|
|
25
|
-
|
26
25
|
whitelist = Helper::LocalizeHelper.getWhitelist
|
27
26
|
|
28
27
|
matchHash.keys
|
29
|
-
|
28
|
+
.map { |match|
|
30
29
|
match.gsub(/^\\"/, "\"").gsub(/\\"$/, "\"")
|
31
30
|
}
|
32
|
-
|
31
|
+
.reject { |match|
|
33
32
|
whitelist.include? match
|
34
33
|
}
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
Helper::LocalizeHelper.showStringOccurrencesFromFile(file, match)
|
39
|
-
end
|
40
|
-
|
41
|
-
if UI.confirm "Extract #{match}?"
|
42
|
-
key = UI.input "Enter key for localization:"
|
43
|
-
Helper::LocalizeHelper.localize_string(match, key, files, params)
|
34
|
+
.each { |match|
|
35
|
+
if params[:lint_only]
|
36
|
+
puts "warning: #{match} is not localized"
|
44
37
|
else
|
45
|
-
|
38
|
+
files.flat_map do |file|
|
39
|
+
Helper::LocalizeHelper.showStringOccurrencesFromFile(file, match)
|
40
|
+
end
|
41
|
+
|
42
|
+
if UI.confirm "Extract #{match}?"
|
43
|
+
key = UI.input "Enter key for localization:"
|
44
|
+
Helper::LocalizeHelper.localize_string(match, key, files, params)
|
45
|
+
else
|
46
|
+
Helper::LocalizeHelper.addToWhitelist(match)
|
47
|
+
end
|
46
48
|
end
|
47
49
|
}
|
48
50
|
end
|
@@ -67,29 +69,40 @@ module Fastlane
|
|
67
69
|
def self.available_options
|
68
70
|
[
|
69
71
|
FastlaneCore::ConfigItem.new(key: :localize_project,
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
72
|
+
env_name: "FL_LOCALIZE_PROJECT", # The name of the environment variable
|
73
|
+
description: "The project to localize", # a short description of this parameter
|
74
|
+
is_string: true, # true: verifies the input is a string, false: every kind of value
|
75
|
+
default_value: Helper::LocalizeHelper.getProject(nil).path # the default value if the user didn't provide one
|
76
|
+
),
|
77
|
+
FastlaneCore::ConfigItem.new(key: :localize_target,
|
78
|
+
env_name: "FL_LOCALIZE_TARGET", # The name of the environment variable
|
79
|
+
description: "The target to localize", # a short description of this parameter
|
80
|
+
is_string: true, # true: verifies the input is a string, false: every kind of value
|
81
|
+
default_value: Helper::LocalizeHelper.getTargetName(nil) # the default value if the user didn't provide one
|
82
|
+
),
|
75
83
|
FastlaneCore::ConfigItem.new(key: :use_swiftgen,
|
76
84
|
env_name: "FL_LOCALIZE_USE_SWIFTGEN", # The name of the environment variable
|
77
85
|
description: "Localize using Swiftgens L10n ", # a short description of this parameter
|
78
86
|
is_string: false, # true: verifies the input is a string, false: every kind of value
|
79
87
|
default_value: false # the default value if the user didn't provide one
|
80
|
-
|
88
|
+
),
|
81
89
|
FastlaneCore::ConfigItem.new(key: :strings_file,
|
82
90
|
env_name: "FL_LOCALIZE_STRINGS_FILE",
|
83
91
|
description: "The stringsfile to write to",
|
84
92
|
is_string: true, # true: verifies the input is a string, false: every kind of value
|
85
93
|
default_value: "Localizable.strings" # the default value if the user didn't provide one,
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
94
|
+
),
|
95
|
+
FastlaneCore::ConfigItem.new(key: :file_filter,
|
96
|
+
env_name: "FL_LOCALIZE_FILE_FILTER",
|
97
|
+
description: "Filter strings for file paths to ignore, separated by commas",
|
98
|
+
optional: true,
|
99
|
+
is_string: false),
|
100
|
+
FastlaneCore::ConfigItem.new(key: :lint_only,
|
101
|
+
env_name: "FL_LOCALIZE_LINT_ONLY", # The name of the environment variable
|
102
|
+
description: "Only lint and print warnings for unlocalized strings. ", # a short description of this parameter
|
103
|
+
is_string: false, # true: verifies the input is a string, false: every kind of value
|
104
|
+
default_value: false # the default value if the user didn't provide one
|
105
|
+
),
|
93
106
|
]
|
94
107
|
end
|
95
108
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "fastlane_core/ui/ui"
|
2
2
|
|
3
3
|
module Fastlane
|
4
4
|
UI = FastlaneCore::UI unless Fastlane.const_defined?("UI")
|
@@ -9,8 +9,7 @@ module Fastlane
|
|
9
9
|
# as `Helper::LocalizeHelper.your_method`
|
10
10
|
#
|
11
11
|
|
12
|
-
|
13
|
-
def self.getProject(options)
|
12
|
+
def self.getProjectPath(options)
|
14
13
|
projectPath = nil
|
15
14
|
|
16
15
|
unless options.nil?
|
@@ -22,52 +21,72 @@ module Fastlane
|
|
22
21
|
end
|
23
22
|
|
24
23
|
if projectPath.nil?
|
25
|
-
projectPath = Dir.entries(
|
24
|
+
projectPath = Dir.entries(".").select { |f| f.end_with?(".xcodeproj") }.first
|
26
25
|
end
|
27
26
|
|
28
27
|
if projectPath.nil?
|
29
28
|
fail "no xcodeproject found"
|
30
29
|
end
|
31
30
|
|
32
|
-
|
31
|
+
projectPath
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.getProject(options)
|
35
|
+
project = Xcodeproj::Project.open(self.getProjectPath(options))
|
33
36
|
|
34
37
|
project
|
35
38
|
end
|
36
39
|
|
37
|
-
def self.
|
40
|
+
def self.getTargetName(options)
|
41
|
+
project = self.getProject(options)
|
42
|
+
|
38
43
|
targetName = nil
|
39
44
|
|
40
|
-
|
41
|
-
|
42
|
-
|
45
|
+
unless options.nil?
|
46
|
+
targetName = options[:localize_target]
|
47
|
+
end
|
48
|
+
|
49
|
+
if targetName.nil?
|
50
|
+
targetName = ENV["TARGET_NAME"]
|
51
|
+
end
|
43
52
|
|
44
53
|
if targetName.nil?
|
45
|
-
targetName = project.targets.
|
54
|
+
targetName = project.targets.map { |target| target.name.to_s }.first
|
46
55
|
end
|
47
56
|
|
48
57
|
if targetName.nil?
|
49
58
|
fail "no target found"
|
50
59
|
end
|
51
60
|
|
61
|
+
targetName
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.getTarget(options)
|
65
|
+
project = self.getProject(options)
|
66
|
+
targetName = self.getTargetName(options)
|
67
|
+
|
52
68
|
target = project.targets.select { |target| target.name.eql? targetName }.first
|
53
69
|
|
54
70
|
if target.nil?
|
55
|
-
fail
|
71
|
+
fail "no target"
|
56
72
|
end
|
57
73
|
|
58
74
|
target
|
59
75
|
end
|
60
76
|
|
61
77
|
def self.codeFiles(target, options)
|
78
|
+
if options[:file_filter].nil?
|
79
|
+
filter = []
|
80
|
+
else
|
81
|
+
filter = (options[:file_filter]).split(",")
|
82
|
+
end
|
62
83
|
|
63
|
-
|
64
|
-
|
65
|
-
codeFiles = target.source_build_phase.files.to_a.map do |pbx_build_file|
|
66
|
-
pbx_build_file.file_ref.real_path.to_s
|
84
|
+
codeFiles = target.source_build_phase.files.to_a.map do |pbx_build_file|
|
85
|
+
pbx_build_file.file_ref.real_path.to_s
|
67
86
|
end.select do |path|
|
68
|
-
|
87
|
+
path.end_with?(".swift")
|
69
88
|
end.select do |path|
|
70
|
-
|
89
|
+
bool = true
|
71
90
|
|
72
91
|
filter.each { |filter|
|
73
92
|
if path.include? filter
|
@@ -77,28 +96,24 @@ module Fastlane
|
|
77
96
|
|
78
97
|
next bool
|
79
98
|
end.select do |path|
|
80
|
-
|
81
|
-
|
99
|
+
File.exists?(path)
|
100
|
+
end
|
82
101
|
|
83
102
|
codeFiles
|
84
103
|
end
|
85
104
|
|
86
105
|
def self.stringsFromFile(file)
|
87
|
-
|
88
106
|
strings = File.readlines(file).to_s.enum_for(:scan,
|
89
|
-
|
90
|
-
).flat_map {Regexp.last_match}
|
107
|
+
/(?<!\#imageLiteral\(resourceName:|\#imageLiteral\(resourceName: |NSLocalizedString\()\\"[^\\"\r\n]*\\"/).flat_map { Regexp.last_match }
|
91
108
|
return strings
|
92
109
|
end
|
93
110
|
|
94
111
|
def self.showStringOccurrencesFromFile(file, string)
|
95
|
-
|
96
112
|
line_array = File.readlines(file)
|
97
113
|
|
98
114
|
File.open(file).each_with_index { |line, index|
|
99
|
-
if line =~ /(?<!\#imageLiteral\(resourceName:|\#imageLiteral\(resourceName: |NSLocalizedString\()#{string}/
|
100
|
-
|
101
|
-
hits = line_array[index-2 .. index-1] + [line_array[index].green] + line_array[index+1 .. index+2]
|
115
|
+
if line =~ /(?<!\#imageLiteral\(resourceName:|\#imageLiteral\(resourceName: |NSLocalizedString\()#{Regexp.escape(string)}/
|
116
|
+
hits = line_array[index - 2..index - 1] + [line_array[index].green] + line_array[index + 1..index + 2]
|
102
117
|
UI.message "In file #{file} (line #{index}): \n\n#{hits.join()}"
|
103
118
|
end
|
104
119
|
}
|
@@ -109,8 +124,8 @@ module Fastlane
|
|
109
124
|
end
|
110
125
|
|
111
126
|
def self.addToWhitelist(string)
|
112
|
-
open(whitelistFilename,
|
113
|
-
|
127
|
+
open(whitelistFilename, "a") { |f|
|
128
|
+
f.puts string
|
114
129
|
}
|
115
130
|
UI.message "Added \"#{string}\" to #{whitelistFilename}"
|
116
131
|
end
|
@@ -124,15 +139,15 @@ module Fastlane
|
|
124
139
|
end
|
125
140
|
|
126
141
|
def self.localize_string(string, key, files, params)
|
127
|
-
open(params[:strings_file],
|
128
|
-
|
142
|
+
open(params[:strings_file], "a") { |f|
|
143
|
+
f.puts "\"#{key}\" = #{string};"
|
129
144
|
}
|
130
145
|
files.each do |file_name|
|
131
146
|
text = File.read(file_name)
|
132
147
|
|
133
148
|
new_contents = text.gsub(string, replacementString(key, params))
|
134
149
|
|
135
|
-
File.open(file_name, "w") {|file| file.puts new_contents }
|
150
|
+
File.open(file_name, "w") { |file| file.puts new_contents }
|
136
151
|
end
|
137
152
|
|
138
153
|
UI.message "Replaced \"#{string}\" with \"#{replacementString(key, params)}\""
|
@@ -140,7 +155,14 @@ module Fastlane
|
|
140
155
|
|
141
156
|
def self.replacementString(key, params)
|
142
157
|
if params[:use_swiftgen]
|
143
|
-
|
158
|
+
swiftgenKey = key.gsub(".", "_").split("_").inject { |m, p|
|
159
|
+
letters = p.split("")
|
160
|
+
letters.first.upcase!
|
161
|
+
p2 = letters.join
|
162
|
+
m + p2
|
163
|
+
}
|
164
|
+
|
165
|
+
return "L10n.#{swiftgenKey}"
|
144
166
|
else
|
145
167
|
return "NSLocalizedString(\"#{key}\")"
|
146
168
|
end
|
@@ -1,10 +1,10 @@
|
|
1
|
-
require
|
1
|
+
require "fastlane/plugin/localize/version"
|
2
2
|
|
3
3
|
module Fastlane
|
4
4
|
module Localize
|
5
5
|
# Return all .rb files inside the "actions" and "helper" directory
|
6
6
|
def self.all_classes
|
7
|
-
Dir[File.expand_path(
|
7
|
+
Dir[File.expand_path("**/{actions,helper}/*.rb", File.dirname(__FILE__))]
|
8
8
|
end
|
9
9
|
end
|
10
10
|
end
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fastlane-plugin-localize
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wolfgang Lutz
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-03-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
@@ -25,7 +25,21 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: fastlane
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.204.3
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.204.3
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
45
|
- - ">="
|
@@ -39,7 +53,7 @@ dependencies:
|
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: '0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
56
|
+
name: rake
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
59
|
- - ">="
|
@@ -53,7 +67,7 @@ dependencies:
|
|
53
67
|
- !ruby/object:Gem::Version
|
54
68
|
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
70
|
+
name: rspec
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
73
|
- - ">="
|
@@ -67,7 +81,7 @@ dependencies:
|
|
67
81
|
- !ruby/object:Gem::Version
|
68
82
|
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
84
|
+
name: rspec_junit_formatter
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
72
86
|
requirements:
|
73
87
|
- - ">="
|
@@ -86,16 +100,16 @@ dependencies:
|
|
86
100
|
requirements:
|
87
101
|
- - '='
|
88
102
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
103
|
+
version: 1.12.1
|
90
104
|
type: :development
|
91
105
|
prerelease: false
|
92
106
|
version_requirements: !ruby/object:Gem::Requirement
|
93
107
|
requirements:
|
94
108
|
- - '='
|
95
109
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
110
|
+
version: 1.12.1
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
|
-
name: rubocop-
|
112
|
+
name: rubocop-performance
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
100
114
|
requirements:
|
101
115
|
- - ">="
|
@@ -109,7 +123,7 @@ dependencies:
|
|
109
123
|
- !ruby/object:Gem::Version
|
110
124
|
version: '0'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
126
|
+
name: rubocop-require_tools
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
114
128
|
requirements:
|
115
129
|
- - ">="
|
@@ -123,20 +137,20 @@ dependencies:
|
|
123
137
|
- !ruby/object:Gem::Version
|
124
138
|
version: '0'
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
140
|
+
name: simplecov
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
128
142
|
requirements:
|
129
143
|
- - ">="
|
130
144
|
- !ruby/object:Gem::Version
|
131
|
-
version:
|
145
|
+
version: '0'
|
132
146
|
type: :development
|
133
147
|
prerelease: false
|
134
148
|
version_requirements: !ruby/object:Gem::Requirement
|
135
149
|
requirements:
|
136
150
|
- - ">="
|
137
151
|
- !ruby/object:Gem::Version
|
138
|
-
version:
|
139
|
-
description:
|
152
|
+
version: '0'
|
153
|
+
description:
|
140
154
|
email: wlut@num42.de
|
141
155
|
executables: []
|
142
156
|
extensions: []
|
@@ -152,7 +166,7 @@ homepage: https://github.com/num42/fastlane-plugin-localize
|
|
152
166
|
licenses:
|
153
167
|
- MIT
|
154
168
|
metadata: {}
|
155
|
-
post_install_message:
|
169
|
+
post_install_message:
|
156
170
|
rdoc_options: []
|
157
171
|
require_paths:
|
158
172
|
- lib
|
@@ -160,16 +174,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
160
174
|
requirements:
|
161
175
|
- - ">="
|
162
176
|
- !ruby/object:Gem::Version
|
163
|
-
version: '
|
177
|
+
version: '2.5'
|
164
178
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
165
179
|
requirements:
|
166
180
|
- - ">="
|
167
181
|
- !ruby/object:Gem::Version
|
168
182
|
version: '0'
|
169
183
|
requirements: []
|
170
|
-
|
171
|
-
|
172
|
-
signing_key:
|
184
|
+
rubygems_version: 3.2.32
|
185
|
+
signing_key:
|
173
186
|
specification_version: 4
|
174
187
|
summary: Searches the code for extractable strings and allows interactive extraction
|
175
188
|
to .strings file.
|