translatomatic 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|