translatomatic 0.1.1 → 0.1.2
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 +4 -4
- data/.gitattributes +19 -0
- data/.gitignore +0 -0
- data/.travis.yml +7 -7
- data/.yardopts +9 -0
- data/Gemfile +4 -4
- data/Guardfile +0 -0
- data/README.de.md +61 -16
- data/README.es.md +60 -15
- data/README.fr.md +61 -16
- data/README.it.md +60 -15
- data/README.ja.md +59 -14
- data/README.ko.md +137 -0
- data/README.md +58 -13
- data/README.ms.md +137 -0
- data/README.pt.md +137 -0
- data/README.ru.md +137 -0
- data/README.sv.md +137 -0
- data/README.zh.md +137 -0
- data/bin/setup +8 -8
- data/bin/translatomatic +6 -6
- data/bin/travis +1 -1
- data/config/locales/translatomatic/de.yml +104 -0
- data/config/locales/translatomatic/en.yml +101 -0
- data/config/locales/translatomatic/es.yml +105 -0
- data/config/locales/translatomatic/fr.yml +105 -0
- data/config/locales/translatomatic/it.yml +103 -0
- data/config/locales/translatomatic/ja.yml +102 -0
- data/config/locales/translatomatic/ko.yml +101 -0
- data/config/locales/translatomatic/ms.yml +103 -0
- data/config/locales/translatomatic/pt.yml +105 -0
- data/config/locales/translatomatic/ru.yml +103 -0
- data/config/locales/translatomatic/sv.yml +103 -0
- data/config/locales/translatomatic/zh.yml +102 -0
- data/db/migrate/201712170000_initial.rb +2 -1
- data/lib/translatomatic/cli/base.rb +73 -0
- data/lib/translatomatic/cli/common_options.rb +14 -0
- data/lib/translatomatic/cli/config.rb +81 -0
- data/lib/translatomatic/cli/database.rb +29 -0
- data/lib/translatomatic/cli/main.rb +112 -0
- data/lib/translatomatic/cli/translate.rb +146 -0
- data/lib/translatomatic/cli.rb +8 -216
- data/lib/translatomatic/config.rb +143 -0
- data/lib/translatomatic/converter.rb +196 -149
- data/lib/translatomatic/converter_stats.rb +18 -14
- data/lib/translatomatic/database.rb +35 -37
- data/lib/translatomatic/escaped_unicode.rb +1 -1
- data/lib/translatomatic/extractor/base.rb +2 -0
- data/lib/translatomatic/extractor/ruby.rb +1 -0
- data/lib/translatomatic/extractor.rb +1 -0
- data/lib/translatomatic/http_request.rb +43 -14
- data/lib/translatomatic/locale.rb +28 -4
- data/lib/translatomatic/logger.rb +21 -13
- data/lib/translatomatic/model/locale.rb +5 -1
- data/lib/translatomatic/model/text.rb +2 -0
- data/lib/translatomatic/model.rb +1 -0
- data/lib/translatomatic/option.rb +75 -10
- data/lib/translatomatic/progress_updater.rb +7 -3
- data/lib/translatomatic/resource_file/base.rb +41 -18
- data/lib/translatomatic/resource_file/html.rb +11 -14
- data/lib/translatomatic/resource_file/markdown.rb +13 -12
- data/lib/translatomatic/resource_file/plist.rb +3 -14
- data/lib/translatomatic/resource_file/properties.rb +21 -3
- data/lib/translatomatic/resource_file/resw.rb +1 -0
- data/lib/translatomatic/resource_file/text.rb +1 -0
- data/lib/translatomatic/resource_file/xcode_strings.rb +23 -14
- data/lib/translatomatic/resource_file/xml.rb +34 -22
- data/lib/translatomatic/resource_file/yaml.rb +39 -5
- data/lib/translatomatic/resource_file.rb +7 -5
- data/lib/translatomatic/string.rb +40 -12
- data/lib/translatomatic/tmx/document.rb +11 -12
- data/lib/translatomatic/tmx/translation_unit.rb +5 -1
- data/lib/translatomatic/tmx.rb +2 -0
- data/lib/translatomatic/translation.rb +30 -0
- data/lib/translatomatic/translation_result.rb +45 -45
- data/lib/translatomatic/translator/base.rb +128 -83
- data/lib/translatomatic/translator/frengly.rb +62 -57
- data/lib/translatomatic/translator/google.rb +35 -31
- data/lib/translatomatic/translator/microsoft.rb +41 -33
- data/lib/translatomatic/translator/my_memory.rb +68 -64
- data/lib/translatomatic/translator/yandex.rb +56 -39
- data/lib/translatomatic/translator.rb +99 -63
- data/lib/translatomatic/util.rb +31 -1
- data/lib/translatomatic/version.rb +4 -1
- data/lib/translatomatic.rb +17 -0
- data/translatomatic.gemspec +5 -4
- metadata +56 -16
@@ -2,24 +2,38 @@ require 'securerandom'
|
|
2
2
|
require 'net/http'
|
3
3
|
|
4
4
|
module Translatomatic
|
5
|
+
# HTTP request
|
6
|
+
# wrapper for Net::HTTP functionality
|
5
7
|
class HTTPRequest
|
6
8
|
|
9
|
+
# @return [String] the text to use to denote multipart boundaries. By
|
10
|
+
# default, a random hexadecimal string is used.
|
7
11
|
attr_accessor :multipart_boundary
|
8
12
|
|
13
|
+
# @param url [String,URI] URL of the request
|
14
|
+
# @return [Translatomatic::HTTPRequest] Create a new request
|
9
15
|
def initialize(url)
|
10
16
|
@uri = url.respond_to?(:host) ? url : URI.parse(url)
|
11
17
|
@multipart_boundary = SecureRandom.hex(16)
|
12
18
|
end
|
13
19
|
|
20
|
+
# Start the HTTP request. Yields a http object.
|
21
|
+
# @param options [Hash<Symbol,Object>] Request options
|
22
|
+
# @return [Object] Result of the block
|
14
23
|
def start(options = {})
|
15
24
|
options = options.merge(use_ssl: @uri.scheme == "https")
|
25
|
+
result = nil
|
16
26
|
Net::HTTP.start(@uri.host, @uri.port, options) do |http|
|
17
27
|
@http = http
|
18
|
-
yield http
|
28
|
+
result = yield http
|
19
29
|
end
|
20
30
|
@http = nil
|
31
|
+
result
|
21
32
|
end
|
22
33
|
|
34
|
+
# Send a HTTP GET request
|
35
|
+
# @param query [Hash<String,String>] Optional query parameters
|
36
|
+
# @return [Net::HTTP::Response]
|
23
37
|
def get(query = nil)
|
24
38
|
uri = @uri
|
25
39
|
if query
|
@@ -31,6 +45,9 @@ module Translatomatic
|
|
31
45
|
send_request(request)
|
32
46
|
end
|
33
47
|
|
48
|
+
# Send an HTTP POST request
|
49
|
+
# @param body [String,Hash] Body of the request
|
50
|
+
# @return [Net::HTTP::Response]
|
34
51
|
def post(body, options = {})
|
35
52
|
request = Net::HTTP::Post.new(@uri)
|
36
53
|
request['User-Agent'] = USER_AGENT
|
@@ -40,6 +57,7 @@ module Translatomatic
|
|
40
57
|
content_type = "multipart/form-data; boundary=#{@multipart_boundary}"
|
41
58
|
request.body = multipartify(body)
|
42
59
|
elsif body.kind_of?(Hash)
|
60
|
+
# set_form_data does url encoding
|
43
61
|
request.set_form_data(body)
|
44
62
|
else
|
45
63
|
request.body = body
|
@@ -49,10 +67,14 @@ module Translatomatic
|
|
49
67
|
send_request(request)
|
50
68
|
end
|
51
69
|
|
70
|
+
# Create a file parameter for a multipart POST request
|
71
|
+
# @return [FileParam] A new file parameter
|
52
72
|
def file(*args)
|
53
73
|
FileParam.new(*args)
|
54
74
|
end
|
55
75
|
|
76
|
+
# Create a parameter for a multipart POST request
|
77
|
+
# @return [Param] A new parameter
|
56
78
|
def param(*args)
|
57
79
|
Param.new(*args)
|
58
80
|
end
|
@@ -65,17 +87,19 @@ module Translatomatic
|
|
65
87
|
class Param
|
66
88
|
attr_accessor :key, :value
|
67
89
|
|
68
|
-
|
69
|
-
|
70
|
-
@value = value
|
71
|
-
end
|
72
|
-
|
90
|
+
# @return [String] Representation of this parameter as it appears
|
91
|
+
# within a multipart post request.
|
73
92
|
def to_s
|
74
93
|
return header(header_data) + "\r\n#{value}\r\n"
|
75
94
|
end
|
76
95
|
|
77
96
|
private
|
78
97
|
|
98
|
+
def initialize(key:, value:)
|
99
|
+
@key = key
|
100
|
+
@value = value
|
101
|
+
end
|
102
|
+
|
79
103
|
def header_data
|
80
104
|
name = CGI::escape(key.to_s)
|
81
105
|
{ "Content-Disposition": "form-data", name: %Q("#{name}") }
|
@@ -97,13 +121,7 @@ module Translatomatic
|
|
97
121
|
class FileParam < Param
|
98
122
|
attr_accessor :filename, :content, :mime_type
|
99
123
|
|
100
|
-
|
101
|
-
@key = key
|
102
|
-
@filename = filename
|
103
|
-
@content = content
|
104
|
-
@mime_type = mime_type
|
105
|
-
end
|
106
|
-
|
124
|
+
# (see Param#to_s)
|
107
125
|
def to_s
|
108
126
|
return header(header_data) +
|
109
127
|
header("Content-Type": mime_type) + "\r\n#{content}\r\n"
|
@@ -111,6 +129,13 @@ module Translatomatic
|
|
111
129
|
|
112
130
|
private
|
113
131
|
|
132
|
+
def initialize(key:, filename:, content:, mime_type:)
|
133
|
+
@key = key
|
134
|
+
@filename = filename
|
135
|
+
@content = content
|
136
|
+
@mime_type = mime_type
|
137
|
+
end
|
138
|
+
|
114
139
|
def header_data
|
115
140
|
super.merge({ filename: %Q("#{filename}") })
|
116
141
|
end
|
@@ -124,7 +149,11 @@ module Translatomatic
|
|
124
149
|
end
|
125
150
|
|
126
151
|
def send_request(req)
|
127
|
-
|
152
|
+
if @http
|
153
|
+
response = @http.request(req)
|
154
|
+
else
|
155
|
+
response = start { |http| http.request(req) }
|
156
|
+
end
|
128
157
|
raise response.body unless response.kind_of? Net::HTTPSuccess
|
129
158
|
response
|
130
159
|
end
|
@@ -1,18 +1,37 @@
|
|
1
|
+
# Represents a locale
|
2
|
+
# @see https://en.wikipedia.org/wiki/Locale_(computer_software)
|
1
3
|
class Translatomatic::Locale
|
2
4
|
|
5
|
+
# @return [String] ISO 639-1 language
|
3
6
|
attr_reader :language
|
7
|
+
|
8
|
+
# @return [String] ISO 15924 script
|
4
9
|
attr_reader :script
|
10
|
+
|
11
|
+
# @return [String] ISO 3166-1 alpha-2 country code
|
5
12
|
attr_reader :region
|
6
13
|
|
14
|
+
# Parse the given tag
|
15
|
+
# @param tag [String] A string representing a locale
|
16
|
+
# @param validate [boolean] If true, return nil if the locale is invalid
|
17
|
+
# @return [Locale] A locale object
|
7
18
|
def self.parse(tag, validate = true)
|
8
|
-
|
19
|
+
return nil if tag.nil?
|
20
|
+
|
21
|
+
locale = tag
|
22
|
+
unless tag.kind_of?(Translatomatic::Locale)
|
23
|
+
tag = tag.to_s.gsub(/_/, '-')
|
24
|
+
locale = new(tag)
|
25
|
+
end
|
9
26
|
validate && !locale.valid? ? nil : locale
|
10
27
|
end
|
11
28
|
|
29
|
+
# @return [Locale] the default locale
|
12
30
|
def self.default
|
13
|
-
|
31
|
+
parse(Translatomatic::Config.instance.default_locale)
|
14
32
|
end
|
15
33
|
|
34
|
+
# @return [Locale] create a new locale object
|
16
35
|
def initialize(tag)
|
17
36
|
data = I18n::Locale::Tag::Rfc4646.tag(tag)
|
18
37
|
if data
|
@@ -22,23 +41,29 @@ class Translatomatic::Locale
|
|
22
41
|
end
|
23
42
|
end
|
24
43
|
|
44
|
+
# @return true if language is a valid ISO 639-1 language
|
25
45
|
def valid?
|
26
|
-
# test if lang is a valid ISO 639-1 language
|
27
46
|
VALID_LANGUAGES.include?(language)
|
28
47
|
end
|
29
48
|
|
49
|
+
# @return [String] Locale as a string
|
30
50
|
def to_s
|
31
51
|
[language, script, region].compact.join("-")
|
32
52
|
end
|
33
53
|
|
54
|
+
# @param other [Object] Another object
|
55
|
+
# @return [boolean] true if the other object is a {Translatomatic::Locale}
|
56
|
+
# object and has equal language, script and region.
|
34
57
|
def eql?(other)
|
35
58
|
other.kind_of?(Translatomatic::Locale) && other.hash == hash
|
36
59
|
end
|
37
60
|
|
61
|
+
# (see #eql?)
|
38
62
|
def ==(other)
|
39
63
|
eql?(other)
|
40
64
|
end
|
41
65
|
|
66
|
+
# @!visibility private
|
42
67
|
def hash
|
43
68
|
[language, script, region].hash
|
44
69
|
end
|
@@ -47,6 +72,5 @@ class Translatomatic::Locale
|
|
47
72
|
|
48
73
|
# list of 2 letter country codes
|
49
74
|
VALID_LANGUAGES = ::I18nData.languages.keys.collect { |i| i.downcase }.sort
|
50
|
-
DEFAULT_LOCALE = parse(I18n.default_locale)
|
51
75
|
|
52
76
|
end
|
@@ -1,6 +1,10 @@
|
|
1
|
-
|
1
|
+
# Logging
|
2
|
+
class Translatomatic::Logger
|
3
|
+
|
4
|
+
# @return [ProgressBar] A progress bar
|
2
5
|
attr_accessor :progressbar
|
3
|
-
|
6
|
+
|
7
|
+
# @return [Translatomatic::Logger] create a new logger instance
|
4
8
|
def initialize
|
5
9
|
@logger = Logger.new(STDOUT)
|
6
10
|
@logger.level = ENV['DEBUG'] ? Logger::DEBUG : Logger::INFO
|
@@ -9,20 +13,24 @@ class Translatomatic::Logger
|
|
9
13
|
end
|
10
14
|
end
|
11
15
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
# Called at the end of translatomatic to clear the progress bar.
|
17
|
+
def finish
|
18
|
+
@finished ||= begin
|
19
|
+
@progressbar.finish if @progressbar
|
20
|
+
true
|
21
|
+
end
|
18
22
|
end
|
19
23
|
|
20
|
-
private
|
24
|
+
private
|
21
25
|
|
22
|
-
def
|
23
|
-
|
24
|
-
@logger.send(name, *args)
|
25
|
-
@progressbar.refresh(force: true) if @progressbar && !@progressbar.stopped?
|
26
|
+
def method_missing(name, *args)
|
27
|
+
handle_logger_method(name, args) if @logger.respond_to?(name)
|
26
28
|
end
|
27
29
|
|
30
|
+
def handle_logger_method(name, args)
|
31
|
+
@progressbar.clear if @progressbar
|
32
|
+
@logger.send(name, *args)
|
33
|
+
@progressbar.refresh(force: true) if @progressbar && !@progressbar.stopped?
|
34
|
+
end
|
35
|
+
|
28
36
|
end
|
@@ -1,11 +1,14 @@
|
|
1
1
|
module Translatomatic
|
2
2
|
module Model
|
3
|
+
# Locale database record.
|
4
|
+
# Used to store translations in the database.
|
3
5
|
class Locale < ActiveRecord::Base
|
4
6
|
has_many :texts, class_name: "Translatomatic::Model::Text"
|
5
7
|
validates_presence_of :language
|
6
8
|
validates_uniqueness_of :language, scope: [:script, :region]
|
7
9
|
|
8
|
-
#
|
10
|
+
# Create a locale record from an I18n::Locale::Tag object or string
|
11
|
+
# @return [Translatomatic::Model::Locale] Locale record
|
9
12
|
def self.from_tag(tag)
|
10
13
|
tag = Translatomatic::Locale.parse(tag)
|
11
14
|
find_or_create_by!({
|
@@ -13,6 +16,7 @@ module Translatomatic
|
|
13
16
|
})
|
14
17
|
end
|
15
18
|
|
19
|
+
# @return [String] Locale as string
|
16
20
|
def to_s
|
17
21
|
[language, script, region].compact.join("-")
|
18
22
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module Translatomatic
|
2
2
|
module Model
|
3
|
+
# Text database record.
|
4
|
+
# Used to store translations in the database.
|
3
5
|
class Text < ActiveRecord::Base
|
4
6
|
belongs_to :locale, class_name: "Translatomatic::Model::Locale"
|
5
7
|
belongs_to :from_text, class_name: "Translatomatic::Model::Text"
|
data/lib/translatomatic/model.rb
CHANGED
@@ -1,24 +1,89 @@
|
|
1
1
|
module Translatomatic
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
# Stores details about command line and object constructor options
|
3
|
+
class Option
|
4
|
+
# @return [String] Name of the option
|
5
|
+
attr_reader :name
|
6
|
+
|
7
|
+
# @return [boolean] True if this option is required
|
8
|
+
attr_reader :required
|
9
|
+
|
10
|
+
# @return [boolean] If true, the option can be set via an environment
|
11
|
+
# variable corresponding to the uppercased version of {name}.
|
12
|
+
attr_reader :use_env
|
13
|
+
|
14
|
+
# @return [String] Description of the option
|
15
|
+
attr_reader :description
|
16
|
+
|
17
|
+
# @return [boolean] If true, the option does not appear on the command line
|
18
|
+
# but it can be used in configuration settings
|
19
|
+
attr_reader :hidden
|
20
|
+
|
21
|
+
# @return [Symbol] Type of option, one of:
|
22
|
+
# :string, :hash, :array, :numeric, or :boolean
|
23
|
+
attr_reader :type
|
24
|
+
|
25
|
+
# @return [Object] The default value for this option
|
26
|
+
attr_reader :default
|
27
|
+
|
28
|
+
# Create a new option
|
29
|
+
# @param data [Hash<Symbol,Object>] Attributes as above
|
30
|
+
# @return [Translatomatic::Option] A new option instance
|
5
31
|
def initialize(data = {})
|
6
32
|
@name = data[:name]
|
7
33
|
@required = data[:required]
|
8
34
|
@use_env = data[:use_env]
|
9
|
-
@description = data[:desc]
|
35
|
+
@description = data[:desc]
|
36
|
+
@hidden = data[:hidden]
|
37
|
+
@default = data[:default]
|
38
|
+
@type = data[:type] || :string
|
10
39
|
@data = data
|
11
40
|
end
|
12
|
-
|
13
|
-
|
14
|
-
|
41
|
+
|
42
|
+
# @return [Hash] Option data as a hash
|
43
|
+
def to_hash
|
44
|
+
@data
|
45
|
+
end
|
46
|
+
|
47
|
+
# Retrieve all options from an object or list of objects.
|
48
|
+
# @param object [#options,Array<#options>] Options source
|
49
|
+
# @return [Array<Translatomatic::Option>] options
|
50
|
+
def self.options_from_object(object)
|
51
|
+
options = []
|
52
|
+
if object.respond_to?(:options)
|
53
|
+
options += options_from_object(object.options)
|
54
|
+
elsif object.kind_of?(Array)
|
55
|
+
object.each do |item|
|
56
|
+
if item.kind_of?(Translatomatic::Option)
|
57
|
+
options << item
|
58
|
+
elsif item.respond_to?(:options)
|
59
|
+
options += options_from_object(item.options)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
options
|
15
64
|
end
|
16
65
|
end
|
66
|
+
|
67
|
+
private
|
17
68
|
|
69
|
+
# @!visibility private
|
18
70
|
module DefineOptions
|
19
|
-
|
20
|
-
|
21
|
-
|
71
|
+
|
72
|
+
# @!visibility private
|
73
|
+
module ClassMethods
|
74
|
+
attr_reader :options
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def define_options(*options)
|
79
|
+
@options = options.collect { |i| Translatomatic::Option.new(i) }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def self.included(klass)
|
86
|
+
klass.extend(ClassMethods)
|
22
87
|
end
|
23
88
|
end
|
24
89
|
end
|
@@ -1,15 +1,19 @@
|
|
1
1
|
# implements Converter listener
|
2
2
|
class Translatomatic::ProgressUpdater
|
3
|
+
# Create a new progress updater
|
4
|
+
# @param progressbar [Progressbar] A ruby-progressbar object
|
3
5
|
def initialize(progressbar)
|
4
6
|
@progressbar = progressbar
|
5
7
|
end
|
6
8
|
|
9
|
+
# @return [Number] the number of translated strings
|
7
10
|
def translated_texts(texts)
|
8
|
-
@progressbar.progress += texts.length
|
11
|
+
@progressbar.progress += texts.length
|
9
12
|
end
|
10
|
-
|
13
|
+
|
14
|
+
# @return [Number] the number of untranslated strings
|
11
15
|
def untranslated_texts(texts)
|
12
|
-
@progressbar.total -= texts.length
|
16
|
+
@progressbar.total -= texts.length
|
13
17
|
end
|
14
18
|
|
15
19
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# Base class for resource file implementations
|
1
2
|
# @abstract Subclasses implement different types of resource files
|
2
3
|
class Translatomatic::ResourceFile::Base
|
3
4
|
|
@@ -15,13 +16,13 @@ class Translatomatic::ResourceFile::Base
|
|
15
16
|
# Create a new resource file.
|
16
17
|
# If locale is unspecified, attempts to determine the locale of the file
|
17
18
|
# automatically, and if that fails, uses the default locale.
|
18
|
-
# @param [String]
|
19
|
-
# @param [String]
|
19
|
+
# @param path [String] Path to the file
|
20
|
+
# @param locale [String] Locale of the file contents
|
20
21
|
# @return [Translatomatic::ResourceFile::Base] the resource file.
|
21
22
|
def initialize(path, locale = nil)
|
22
23
|
@path = path.kind_of?(Pathname) ? path : Pathname.new(path)
|
23
|
-
@locale = locale || detect_locale || Translatomatic::Locale.default
|
24
|
-
raise "
|
24
|
+
@locale = Translatomatic::Locale.parse(locale || detect_locale || Translatomatic::Locale.default)
|
25
|
+
raise t("resource.unknown_locale") unless @locale && @locale.language
|
25
26
|
@valid = false
|
26
27
|
@properties = {}
|
27
28
|
end
|
@@ -32,7 +33,7 @@ class Translatomatic::ResourceFile::Base
|
|
32
33
|
end
|
33
34
|
|
34
35
|
# Create a path for the current resource file with a given locale
|
35
|
-
# @param [String]
|
36
|
+
# @param locale [String] The target locale
|
36
37
|
# @return [Pathname] The path of this resource file modified for the given locale
|
37
38
|
def locale_path(locale)
|
38
39
|
basename = path.sub_ext('').basename.to_s
|
@@ -54,7 +55,7 @@ class Translatomatic::ResourceFile::Base
|
|
54
55
|
end
|
55
56
|
|
56
57
|
# Set all properties
|
57
|
-
# @param [Hash<String,String>]
|
58
|
+
# @param properties [Hash<String,String>] New properties
|
58
59
|
def properties=(properties)
|
59
60
|
# use set rather that set @properties directly as subclasses override set()
|
60
61
|
properties.each do |key, value|
|
@@ -63,18 +64,18 @@ class Translatomatic::ResourceFile::Base
|
|
63
64
|
end
|
64
65
|
|
65
66
|
# Get the value of a property
|
66
|
-
# @param [String]
|
67
|
+
# @param key [String] The name of the property
|
67
68
|
# @return [String] The value of the property
|
68
|
-
def get(
|
69
|
-
@properties[
|
69
|
+
def get(key)
|
70
|
+
@properties[key]
|
70
71
|
end
|
71
72
|
|
72
73
|
# Set a property
|
73
|
-
# @param [String]
|
74
|
-
# @param [String]
|
74
|
+
# @param key [String] The name of the property
|
75
|
+
# @param value [String] The new value of the property
|
75
76
|
# @return [String] The new value of the property
|
76
|
-
def set(
|
77
|
-
@properties[
|
77
|
+
def set(key, value)
|
78
|
+
@properties[key] = value
|
78
79
|
end
|
79
80
|
|
80
81
|
# Test if the current resource file is valid
|
@@ -84,8 +85,8 @@ class Translatomatic::ResourceFile::Base
|
|
84
85
|
end
|
85
86
|
|
86
87
|
# Save the resource file.
|
87
|
-
# @param [Pathname]
|
88
|
-
# @param [Hash<Symbol, Object>]
|
88
|
+
# @param target [Pathname] The destination path
|
89
|
+
# @param options [Hash<Symbol, Object>] Output format options
|
89
90
|
# @return [void]
|
90
91
|
def save(target = path, options = {})
|
91
92
|
raise "save(path) must be implemented by subclass"
|
@@ -93,9 +94,10 @@ class Translatomatic::ResourceFile::Base
|
|
93
94
|
|
94
95
|
# @return [String] String representation of this file
|
95
96
|
def to_s
|
96
|
-
|
97
|
+
path.basename.to_s
|
97
98
|
end
|
98
99
|
|
100
|
+
# @return [Array<String>] All property values split into sentences
|
99
101
|
def sentences
|
100
102
|
sentences = []
|
101
103
|
properties.values.each do |value|
|
@@ -105,13 +107,34 @@ class Translatomatic::ResourceFile::Base
|
|
105
107
|
sentences
|
106
108
|
end
|
107
109
|
|
110
|
+
# @return [boolean] true if this resource file supports variable interpolation
|
111
|
+
def supports_variable_interpolation?
|
112
|
+
false
|
113
|
+
end
|
114
|
+
|
115
|
+
# Create an interpolated variable string.
|
116
|
+
# @return [String] A string representing the interpolated variable, or
|
117
|
+
# nil if this resource file doesn't support variable interpolation.
|
118
|
+
def create_variable(name)
|
119
|
+
return nil unless supports_variable_interpolation?
|
120
|
+
raise "create_variable(name) must be implemented by subclass"
|
121
|
+
end
|
122
|
+
|
123
|
+
# @return [Regexp] A regexp used to match interpolated variables
|
124
|
+
def variable_regex
|
125
|
+
return nil unless supports_variable_interpolation?
|
126
|
+
raise "variable_regex must be implemented by subclass"
|
127
|
+
end
|
128
|
+
|
108
129
|
private
|
109
130
|
|
110
131
|
include Translatomatic::Util
|
111
132
|
|
112
133
|
def created_by
|
113
|
-
|
114
|
-
|
134
|
+
t("resource.created_by", app: "Translatomatic",
|
135
|
+
version: Translatomatic::VERSION, date: I18n.l(DateTime.now),
|
136
|
+
locale: locale.language
|
137
|
+
)
|
115
138
|
end
|
116
139
|
|
117
140
|
# detect locale from filename
|
@@ -1,4 +1,5 @@
|
|
1
1
|
module Translatomatic::ResourceFile
|
2
|
+
# HTML resource file
|
2
3
|
class HTML < XML
|
3
4
|
|
4
5
|
# (see Translatomatic::ResourceFile::Base.extensions)
|
@@ -17,30 +18,26 @@ module Translatomatic::ResourceFile
|
|
17
18
|
return strip_extensions.sub_ext("." + new_extension)
|
18
19
|
else
|
19
20
|
# add locale extension
|
20
|
-
ext = path.extname
|
21
|
+
ext = path.extname
|
21
22
|
# TODO: need configurable order for locale & ext here?
|
22
|
-
#path.sub_ext("#{ext}." + locale.to_s)
|
23
|
+
#path.sub_ext("#{ext}." + locale.to_s)
|
23
24
|
path.sub_ext("." + locale.to_s + ext)
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
27
28
|
# (see Translatomatic::ResourceFile::Base#save)
|
28
|
-
def save(target = path, options = {})
|
29
|
-
if @doc
|
30
|
-
add_created_by unless options[:no_created_by]
|
31
|
-
target.write(@doc.to_html)
|
29
|
+
def save(target = path, options = {})
|
30
|
+
if @doc
|
31
|
+
add_created_by unless options[:no_created_by]
|
32
|
+
target.write(@doc.to_html)
|
32
33
|
end
|
33
34
|
end
|
34
35
|
|
35
36
|
private
|
36
|
-
|
37
|
-
def text_nodes_xpath
|
38
|
-
'//*[not(self::code)]/text()'
|
39
|
-
end
|
40
|
-
|
41
|
-
def add_created_by
|
42
|
-
@created_by ||= @doc.root.add_previous_sibling(comment(created_by))
|
43
|
-
end
|
37
|
+
|
38
|
+
def text_nodes_xpath
|
39
|
+
'//*[not(self::code)]/text()'
|
40
|
+
end
|
44
41
|
|
45
42
|
def read_doc(path)
|
46
43
|
Nokogiri::HTML(path.open) do |config|
|
@@ -2,6 +2,7 @@ require 'kramdown'
|
|
2
2
|
require 'reverse_markdown'
|
3
3
|
|
4
4
|
module Translatomatic::ResourceFile
|
5
|
+
# Markdown resource file
|
5
6
|
class Markdown < HTML
|
6
7
|
|
7
8
|
# (see Translatomatic::ResourceFile::Base.extensions)
|
@@ -10,17 +11,17 @@ module Translatomatic::ResourceFile
|
|
10
11
|
end
|
11
12
|
|
12
13
|
# (see Translatomatic::ResourceFile::Base#save)
|
13
|
-
def save(target = path, options = {})
|
14
|
-
if @doc
|
15
|
-
begin
|
16
|
-
add_created_by unless options[:no_created_by]
|
17
|
-
html = @doc.to_html
|
18
|
-
# convert html back to markdown
|
19
|
-
markdown = ReverseMarkdown.convert(html, unknown_tags: :bypass)
|
20
|
-
target.write(markdown.chomp)
|
21
|
-
rescue Exception => e
|
22
|
-
|
23
|
-
end
|
14
|
+
def save(target = path, options = {})
|
15
|
+
if @doc
|
16
|
+
begin
|
17
|
+
add_created_by unless options[:no_created_by]
|
18
|
+
html = @doc.to_html
|
19
|
+
# convert html back to markdown
|
20
|
+
markdown = ReverseMarkdown.convert(html, unknown_tags: :bypass)
|
21
|
+
target.write(markdown.chomp)
|
22
|
+
rescue Exception => e
|
23
|
+
log.error t("resource.error", message: e.message)
|
24
|
+
end
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
@@ -44,7 +45,7 @@ module Translatomatic::ResourceFile
|
|
44
45
|
end
|
45
46
|
init_nodemap(@doc)
|
46
47
|
rescue Exception => e
|
47
|
-
log.error(e.message)
|
48
|
+
log.error t("resource.error", message: e.message)
|
48
49
|
@valid = false
|
49
50
|
{}
|
50
51
|
end
|
@@ -1,25 +1,14 @@
|
|
1
1
|
module Translatomatic::ResourceFile
|
2
|
+
# Property list resource file
|
3
|
+
# @see https://en.wikipedia.org/wiki/Property_list
|
2
4
|
class Plist < XML
|
5
|
+
include Translatomatic::ResourceFile::XCodeStringsLocalePath
|
3
6
|
|
4
7
|
# (see Translatomatic::ResourceFile::Base.extensions)
|
5
8
|
def self.extensions
|
6
9
|
%w{plist}
|
7
10
|
end
|
8
11
|
|
9
|
-
# (see Translatomatic::ResourceFile::Base#locale_path)
|
10
|
-
# @note localization files in XCode use the following file name
|
11
|
-
# convention: Project/locale.lproj/filename
|
12
|
-
# @todo refactor this and xcode_strings.rb to use the same code
|
13
|
-
def locale_path(locale)
|
14
|
-
if path.to_s.match(/\/([-\w]+).lproj\/.+.plist$/)
|
15
|
-
# xcode style
|
16
|
-
filename = path.basename
|
17
|
-
path.parent.parent + (locale.to_s + ".lproj") + filename
|
18
|
-
else
|
19
|
-
super(locale)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
12
|
private
|
24
13
|
|
25
14
|
def text_nodes_xpath
|