fastlane-plugin-translate 0.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 +7 -0
- data/LICENSE +21 -0
- data/README.md +318 -0
- data/lib/fastlane/plugin/translate/actions/translate_with_deepl.rb +547 -0
- data/lib/fastlane/plugin/translate/helper/deepl_language_mapper_helper.rb +99 -0
- data/lib/fastlane/plugin/translate/helper/language_registry_helper.rb +81 -0
- data/lib/fastlane/plugin/translate/helper/translation_progress_helper.rb +78 -0
- data/lib/fastlane/plugin/translate/version.rb +7 -0
- data/lib/fastlane/plugin/translate.rb +20 -0
- metadata +204 -0
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fastlane_core/ui/ui'
|
4
|
+
|
5
|
+
module Fastlane
|
6
|
+
UI = FastlaneCore::UI unless Fastlane.const_defined?(:UI)
|
7
|
+
|
8
|
+
module Helper
|
9
|
+
class LanguageRegistryHelper
|
10
|
+
# Complete list based on Apple's App Store localizations
|
11
|
+
# https://developer.apple.com/help/app-store-connect/reference/app-store-localizations/
|
12
|
+
APPLE_LANGUAGES = {
|
13
|
+
# Language code => { name, regional_variants }
|
14
|
+
'ar' => { name: 'Arabic', variants: [] },
|
15
|
+
'ca' => { name: 'Catalan', variants: [] },
|
16
|
+
'hr' => { name: 'Croatian', variants: [] },
|
17
|
+
'cs' => { name: 'Czech', variants: [] },
|
18
|
+
'da' => { name: 'Danish', variants: [] },
|
19
|
+
'nl' => { name: 'Dutch', variants: [] },
|
20
|
+
'en' => { name: 'English', variants: %w[en-US en-GB en-AU en-CA] },
|
21
|
+
'en-US' => { name: 'English (United States)', variants: [] },
|
22
|
+
'en-GB' => { name: 'English (United Kingdom)', variants: [] },
|
23
|
+
'en-AU' => { name: 'English (Australia)', variants: [] },
|
24
|
+
'en-CA' => { name: 'English (Canada)', variants: [] },
|
25
|
+
'fi' => { name: 'Finnish', variants: [] },
|
26
|
+
'fr' => { name: 'French', variants: ['fr-CA'] },
|
27
|
+
'fr-CA' => { name: 'French (Canada)', variants: [] },
|
28
|
+
'de' => { name: 'German', variants: [] },
|
29
|
+
'el' => { name: 'Greek', variants: [] },
|
30
|
+
'he' => { name: 'Hebrew', variants: [] },
|
31
|
+
'hi' => { name: 'Hindi', variants: [] },
|
32
|
+
'hu' => { name: 'Hungarian', variants: [] },
|
33
|
+
'id' => { name: 'Indonesian', variants: [] },
|
34
|
+
'it' => { name: 'Italian', variants: [] },
|
35
|
+
'ja' => { name: 'Japanese', variants: [] },
|
36
|
+
'ko' => { name: 'Korean', variants: [] },
|
37
|
+
'ms' => { name: 'Malay', variants: [] },
|
38
|
+
'nb' => { name: 'Norwegian Bokmål', variants: [] },
|
39
|
+
'pl' => { name: 'Polish', variants: [] },
|
40
|
+
'pt' => { name: 'Portuguese', variants: %w[pt-BR pt-PT] },
|
41
|
+
'pt-BR' => { name: 'Portuguese (Brazil)', variants: [] },
|
42
|
+
'pt-PT' => { name: 'Portuguese (Portugal)', variants: [] },
|
43
|
+
'ro' => { name: 'Romanian', variants: [] },
|
44
|
+
'ru' => { name: 'Russian', variants: [] },
|
45
|
+
'sk' => { name: 'Slovak', variants: [] },
|
46
|
+
'es' => { name: 'Spanish', variants: %w[es-MX es-ES] },
|
47
|
+
'es-MX' => { name: 'Spanish (Mexico)', variants: [] },
|
48
|
+
'es-ES' => { name: 'Spanish (Spain)', variants: [] },
|
49
|
+
'sv' => { name: 'Swedish', variants: [] },
|
50
|
+
'th' => { name: 'Thai', variants: [] },
|
51
|
+
'tr' => { name: 'Turkish', variants: [] },
|
52
|
+
'uk' => { name: 'Ukrainian', variants: [] },
|
53
|
+
'vi' => { name: 'Vietnamese', variants: [] },
|
54
|
+
'zh' => { name: 'Chinese', variants: %w[zh-Hans zh-Hant zh-HK] },
|
55
|
+
'zh-Hans' => { name: 'Chinese (Simplified)', variants: [] },
|
56
|
+
'zh-Hant' => { name: 'Chinese (Traditional)', variants: [] },
|
57
|
+
'zh-HK' => { name: 'Chinese (Hong Kong)', variants: [] }
|
58
|
+
}.freeze
|
59
|
+
|
60
|
+
def self.supported_languages
|
61
|
+
APPLE_LANGUAGES.keys
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.language_name(code)
|
65
|
+
APPLE_LANGUAGES.dig(code, :name) || code
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.has_variants?(code)
|
69
|
+
APPLE_LANGUAGES.dig(code, :variants)&.any? || false
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.variants(code)
|
73
|
+
APPLE_LANGUAGES.dig(code, :variants) || []
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.valid_language?(code)
|
77
|
+
APPLE_LANGUAGES.key?(code)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fastlane_core/ui/ui'
|
4
|
+
require 'json'
|
5
|
+
require 'time'
|
6
|
+
|
7
|
+
module Fastlane
|
8
|
+
UI = FastlaneCore::UI unless Fastlane.const_defined?(:UI)
|
9
|
+
|
10
|
+
module Helper
|
11
|
+
class TranslationProgressHelper
|
12
|
+
def self.create_progress_tracker(xcstrings_path, target_language)
|
13
|
+
TranslationProgressTracker.new(xcstrings_path, target_language)
|
14
|
+
end
|
15
|
+
|
16
|
+
class TranslationProgressTracker
|
17
|
+
def initialize(xcstrings_path, target_language)
|
18
|
+
@progress_file = "#{xcstrings_path}.translation_progress_#{target_language}.json"
|
19
|
+
@translated_strings = {}
|
20
|
+
end
|
21
|
+
|
22
|
+
def save_translated_strings(translated_strings)
|
23
|
+
progress = load_progress
|
24
|
+
progress['translated_strings'].merge!(translated_strings)
|
25
|
+
progress['last_updated'] = Time.now.iso8601
|
26
|
+
progress['total_translated'] = progress['translated_strings'].size
|
27
|
+
|
28
|
+
File.write(@progress_file, JSON.pretty_generate(progress))
|
29
|
+
UI.verbose("💾 Saved progress: #{translated_strings.size} new translations")
|
30
|
+
end
|
31
|
+
|
32
|
+
def has_progress?
|
33
|
+
File.exist?(@progress_file) && load_progress['translated_strings'].any?
|
34
|
+
end
|
35
|
+
|
36
|
+
def load_progress
|
37
|
+
return default_progress unless File.exist?(@progress_file)
|
38
|
+
|
39
|
+
begin
|
40
|
+
JSON.parse(File.read(@progress_file))
|
41
|
+
rescue JSON::ParserError => e
|
42
|
+
UI.important("⚠️ Corrupted progress file, starting fresh: #{e.message}")
|
43
|
+
default_progress
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def progress_summary
|
48
|
+
progress = load_progress
|
49
|
+
{
|
50
|
+
translated_count: progress['translated_strings'].size,
|
51
|
+
last_updated: progress['last_updated']
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
def cleanup
|
56
|
+
if File.exist?(@progress_file)
|
57
|
+
File.delete(@progress_file)
|
58
|
+
UI.verbose('🗑️ Cleaned up progress file')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def get_translated_strings
|
63
|
+
load_progress['translated_strings']
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def default_progress
|
69
|
+
{
|
70
|
+
'translated_strings' => {},
|
71
|
+
'last_updated' => nil,
|
72
|
+
'total_translated' => 0
|
73
|
+
}
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fastlane/plugin/translate/version'
|
4
|
+
|
5
|
+
module Fastlane
|
6
|
+
module Translate
|
7
|
+
# Return all .rb files inside the "actions" and "helper" directory
|
8
|
+
def self.all_classes
|
9
|
+
Dir[File.expand_path('**/{actions,helper}/*.rb', File.dirname(__FILE__))]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# By default we want to import all available actions and helpers
|
15
|
+
# A plugin can contain any number of actions and plugins
|
16
|
+
Fastlane::Translate.all_classes.each do |current|
|
17
|
+
require current
|
18
|
+
end
|
19
|
+
|
20
|
+
# Helper modules are automatically loaded by the all_classes method above
|
metadata
ADDED
@@ -0,0 +1,204 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fastlane-plugin-translate
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tijs Teulings
|
8
|
+
bindir: bin
|
9
|
+
cert_chain: []
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
|
+
dependencies:
|
12
|
+
- !ruby/object:Gem::Dependency
|
13
|
+
name: deepl-rb
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - ">="
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: 2.5.0
|
19
|
+
type: :runtime
|
20
|
+
prerelease: false
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - ">="
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: 2.5.0
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: bundler
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: fastlane
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 2.0.0
|
47
|
+
type: :development
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 2.0.0
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: pry
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
type: :development
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: rake
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
type: :development
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: rspec
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
type: :development
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
- !ruby/object:Gem::Dependency
|
97
|
+
name: rspec_junit_formatter
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
type: :development
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: rubocop
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - '='
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: 1.50.2
|
117
|
+
type: :development
|
118
|
+
prerelease: false
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - '='
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: 1.50.2
|
124
|
+
- !ruby/object:Gem::Dependency
|
125
|
+
name: rubocop-performance
|
126
|
+
requirement: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '0'
|
131
|
+
type: :development
|
132
|
+
prerelease: false
|
133
|
+
version_requirements: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
- !ruby/object:Gem::Dependency
|
139
|
+
name: rubocop-require_tools
|
140
|
+
requirement: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
type: :development
|
146
|
+
prerelease: false
|
147
|
+
version_requirements: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
- !ruby/object:Gem::Dependency
|
153
|
+
name: simplecov
|
154
|
+
requirement: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - ">="
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0'
|
159
|
+
type: :development
|
160
|
+
prerelease: false
|
161
|
+
version_requirements: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - ">="
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
description: A fastlane plugin to automatically translate iOS Localizable.xcstrings
|
167
|
+
files using DeepL API. Supports progress tracking, formality options, error recovery,
|
168
|
+
and more.
|
169
|
+
email: hello@tijs.org
|
170
|
+
executables: []
|
171
|
+
extensions: []
|
172
|
+
extra_rdoc_files: []
|
173
|
+
files:
|
174
|
+
- LICENSE
|
175
|
+
- README.md
|
176
|
+
- lib/fastlane/plugin/translate.rb
|
177
|
+
- lib/fastlane/plugin/translate/actions/translate_with_deepl.rb
|
178
|
+
- lib/fastlane/plugin/translate/helper/deepl_language_mapper_helper.rb
|
179
|
+
- lib/fastlane/plugin/translate/helper/language_registry_helper.rb
|
180
|
+
- lib/fastlane/plugin/translate/helper/translation_progress_helper.rb
|
181
|
+
- lib/fastlane/plugin/translate/version.rb
|
182
|
+
homepage: https://github.com/tijs/fastlane-plugin-translate
|
183
|
+
licenses:
|
184
|
+
- MIT
|
185
|
+
metadata:
|
186
|
+
rubygems_mfa_required: 'true'
|
187
|
+
rdoc_options: []
|
188
|
+
require_paths:
|
189
|
+
- lib
|
190
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '3.3'
|
195
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
196
|
+
requirements:
|
197
|
+
- - ">="
|
198
|
+
- !ruby/object:Gem::Version
|
199
|
+
version: '0'
|
200
|
+
requirements: []
|
201
|
+
rubygems_version: 3.6.9
|
202
|
+
specification_version: 4
|
203
|
+
summary: Automatically translate iOS Localizable.xcstrings files using DeepL API
|
204
|
+
test_files: []
|