translatomatic 0.1.3 → 0.2.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 +5 -5
- data/.gitattributes +20 -20
- data/.gitignore +19 -15
- data/.rspec +3 -3
- data/.rubocop.yml +28 -0
- data/.translatomatic/config.yml +4 -0
- data/.travis.yml +4 -6
- data/.yardopts +9 -9
- data/Gemfile +8 -4
- data/Guardfile +4 -5
- data/README.de.md +55 -50
- data/README.en.md +177 -0
- data/README.es.md +53 -48
- data/README.fr.md +53 -48
- data/README.it.md +54 -49
- data/README.ja.md +63 -58
- data/README.ko.md +59 -54
- data/README.md +17 -13
- data/README.ms.md +50 -45
- data/README.pt.md +54 -49
- data/README.ru.md +57 -52
- data/README.sv.md +51 -46
- data/README.zh.md +60 -55
- data/Rakefile +3 -3
- data/TODO.txt +6 -0
- data/bin/console +3 -3
- data/bin/translatomatic +4 -2
- data/config/i18n-tasks.yml +130 -0
- data/config/locales/translatomatic/de.yml +141 -99
- data/config/locales/translatomatic/en.yml +129 -89
- data/config/locales/translatomatic/es.yml +136 -99
- data/config/locales/translatomatic/fr.yml +139 -100
- data/config/locales/translatomatic/it.yml +135 -97
- data/config/locales/translatomatic/ja.yml +137 -98
- data/config/locales/translatomatic/ko.yml +138 -98
- data/config/locales/translatomatic/ms.yml +138 -100
- data/config/locales/translatomatic/pt.yml +137 -101
- data/config/locales/translatomatic/ru.yml +136 -98
- data/config/locales/translatomatic/sv.yml +134 -96
- data/config/locales/translatomatic/zh.yml +136 -97
- data/db/migrate/201712170000_initial.rb +2 -3
- data/lib/translatomatic.rb +40 -25
- data/lib/translatomatic/cli.rb +5 -1
- data/lib/translatomatic/cli/base.rb +61 -58
- data/lib/translatomatic/cli/common_options.rb +14 -11
- data/lib/translatomatic/cli/config.rb +96 -91
- data/lib/translatomatic/cli/database.rb +85 -23
- data/lib/translatomatic/cli/main.rb +158 -104
- data/lib/translatomatic/cli/thor.rb +29 -0
- data/lib/translatomatic/cli/translate.rb +134 -157
- data/lib/translatomatic/config.rb +10 -301
- data/lib/translatomatic/config/display.rb +78 -0
- data/lib/translatomatic/config/files.rb +60 -0
- data/lib/translatomatic/config/location_settings.rb +133 -0
- data/lib/translatomatic/config/options.rb +68 -0
- data/lib/translatomatic/config/selector.rb +127 -0
- data/lib/translatomatic/config/settings.rb +148 -0
- data/lib/translatomatic/converter.rb +40 -28
- data/lib/translatomatic/database.rb +127 -110
- data/lib/translatomatic/define_options.rb +4 -5
- data/lib/translatomatic/escaped_unicode.rb +86 -76
- data/lib/translatomatic/extractor.rb +5 -2
- data/lib/translatomatic/extractor/base.rb +12 -12
- data/lib/translatomatic/extractor/ruby.rb +7 -6
- data/lib/translatomatic/file_translator.rb +101 -244
- data/lib/translatomatic/flattenation.rb +39 -0
- data/lib/translatomatic/http.rb +13 -0
- data/lib/translatomatic/http/client.rb +144 -0
- data/lib/translatomatic/http/exception.rb +43 -0
- data/lib/translatomatic/http/file_param.rb +27 -0
- data/lib/translatomatic/http/param.rb +37 -0
- data/lib/translatomatic/http/request.rb +91 -0
- data/lib/translatomatic/i18n.rb +43 -0
- data/lib/translatomatic/locale.rb +71 -59
- data/lib/translatomatic/logger.rb +43 -28
- data/lib/translatomatic/metadata.rb +58 -0
- data/lib/translatomatic/model.rb +4 -2
- data/lib/translatomatic/model/locale.rb +5 -5
- data/lib/translatomatic/model/text.rb +5 -5
- data/lib/translatomatic/option.rb +57 -34
- data/lib/translatomatic/path_utils.rb +126 -0
- data/lib/translatomatic/progress_updater.rb +13 -16
- data/lib/translatomatic/provider.rb +101 -0
- data/lib/translatomatic/provider/base.rb +136 -0
- data/lib/translatomatic/provider/frengly.rb +55 -0
- data/lib/translatomatic/provider/google.rb +78 -0
- data/lib/translatomatic/provider/google_web.rb +50 -0
- data/lib/translatomatic/provider/microsoft.rb +144 -0
- data/lib/translatomatic/provider/my_memory.rb +75 -0
- data/lib/translatomatic/provider/yandex.rb +61 -0
- data/lib/translatomatic/resource_file.rb +59 -53
- data/lib/translatomatic/resource_file/base.rb +171 -237
- data/lib/translatomatic/resource_file/csv.rb +176 -24
- data/lib/translatomatic/resource_file/html.rb +21 -42
- data/lib/translatomatic/resource_file/key_value_support.rb +117 -0
- data/lib/translatomatic/resource_file/markdown.rb +36 -38
- data/lib/translatomatic/resource_file/plist.rb +121 -126
- data/lib/translatomatic/resource_file/po.rb +104 -82
- data/lib/translatomatic/resource_file/properties.rb +48 -77
- data/lib/translatomatic/resource_file/properties.treetop +87 -0
- data/lib/translatomatic/resource_file/resw.rb +56 -41
- data/lib/translatomatic/resource_file/subtitle.rb +86 -54
- data/lib/translatomatic/resource_file/text.rb +18 -18
- data/lib/translatomatic/resource_file/xcode_strings.rb +32 -63
- data/lib/translatomatic/resource_file/xcode_strings.treetop +85 -0
- data/lib/translatomatic/resource_file/xml.rb +94 -81
- data/lib/translatomatic/resource_file/yaml.rb +54 -68
- data/lib/translatomatic/retry_executor.rb +37 -0
- data/lib/translatomatic/slurp.rb +32 -0
- data/lib/translatomatic/string_batcher.rb +50 -0
- data/lib/translatomatic/string_escaping.rb +61 -0
- data/lib/translatomatic/text.rb +263 -0
- data/lib/translatomatic/text_collection.rb +66 -0
- data/lib/translatomatic/tmx.rb +5 -3
- data/lib/translatomatic/tmx/document.rb +107 -82
- data/lib/translatomatic/tmx/translation_unit.rb +19 -18
- data/lib/translatomatic/translation.rb +8 -28
- data/lib/translatomatic/translation/collection.rb +199 -0
- data/lib/translatomatic/translation/fetcher.rb +123 -0
- data/lib/translatomatic/translation/munging.rb +112 -0
- data/lib/translatomatic/translation/result.rb +50 -0
- data/lib/translatomatic/translation/sharer.rb +32 -0
- data/lib/translatomatic/translation/stats.rb +44 -0
- data/lib/translatomatic/translator.rb +91 -88
- data/lib/translatomatic/type_cast.rb +63 -0
- data/lib/translatomatic/util.rb +37 -33
- data/lib/translatomatic/version.rb +2 -2
- data/translatomatic.gemspec +57 -46
- metadata +136 -59
- data/lib/translatomatic/http_request.rb +0 -162
- data/lib/translatomatic/string.rb +0 -188
- data/lib/translatomatic/translation_result.rb +0 -86
- data/lib/translatomatic/translation_stats.rb +0 -31
- data/lib/translatomatic/translator/base.rb +0 -128
- data/lib/translatomatic/translator/frengly.rb +0 -62
- data/lib/translatomatic/translator/google.rb +0 -37
- data/lib/translatomatic/translator/microsoft.rb +0 -41
- data/lib/translatomatic/translator/my_memory.rb +0 -68
- data/lib/translatomatic/translator/yandex.rb +0 -56
@@ -1,91 +1,62 @@
|
|
1
|
-
require '
|
2
|
-
|
3
|
-
module Translatomatic
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
# (see Translatomatic::ResourceFile::Base.is_key_value?)
|
14
|
-
def self.is_key_value?
|
15
|
-
true
|
16
|
-
end
|
17
|
-
|
18
|
-
# (see Translatomatic::ResourceFile::Base.supports_variable_interpolation?)
|
19
|
-
def self.supports_variable_interpolation?
|
20
|
-
true
|
21
|
-
end
|
22
|
-
|
23
|
-
# (see Translatomatic::ResourceFile::Base#save)
|
24
|
-
def save(target = path, options = {})
|
25
|
-
out = ""
|
26
|
-
out += add_created_by unless options[:no_created_by]
|
27
|
-
properties.each do |key, value|
|
28
|
-
# TODO: maintain original line ending format?
|
29
|
-
value = value.gsub("\n", "\\n") if value # convert newlines to \n
|
30
|
-
out += "#{key} = #{value}\n"
|
1
|
+
require 'treetop'
|
2
|
+
|
3
|
+
module Translatomatic
|
4
|
+
module ResourceFile
|
5
|
+
# Properties resource file
|
6
|
+
# @see https://docs.oracle.com/javase/tutorial/essential/environment/properties.html
|
7
|
+
class Properties < Base
|
8
|
+
include KeyValueSupport
|
9
|
+
|
10
|
+
# (see Base.extensions)
|
11
|
+
def self.extensions
|
12
|
+
%w[properties]
|
31
13
|
end
|
32
|
-
# escape unicode characters
|
33
|
-
out = Translatomatic::EscapedUnicode.escape(out)
|
34
|
-
target.write(out)
|
35
|
-
end
|
36
|
-
|
37
|
-
# (see Translatomatic::ResourceFile::Base#create_variable)
|
38
|
-
def create_variable(name)
|
39
|
-
return "{#{name}}"
|
40
|
-
end
|
41
14
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
15
|
+
# (see Base.supports_variable_interpolation?)
|
16
|
+
def self.supports_variable_interpolation?
|
17
|
+
true
|
18
|
+
end
|
46
19
|
|
47
|
-
|
20
|
+
# (see Base.preferred_locale_separator)
|
21
|
+
def self.preferred_locale_separator
|
22
|
+
'_'
|
23
|
+
end
|
48
24
|
|
49
|
-
|
50
|
-
|
51
|
-
|
25
|
+
# (see Base#create_variable)
|
26
|
+
def create_variable(name)
|
27
|
+
"{#{name}}"
|
28
|
+
end
|
52
29
|
|
53
|
-
|
54
|
-
|
55
|
-
|
30
|
+
# (see Base#variable_regex)
|
31
|
+
def variable_regex
|
32
|
+
/\{.*?\}/
|
33
|
+
end
|
56
34
|
|
57
|
-
|
58
|
-
"# #{text}\n"
|
59
|
-
end
|
35
|
+
private
|
60
36
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
contents = Translatomatic::EscapedUnicode.unescape(contents)
|
65
|
-
result = {}
|
66
|
-
contents.gsub!(/\\\s*\n\s*/m, '') # put multi line strings on one line
|
67
|
-
lines = contents.split("\n")
|
37
|
+
Treetop.load(File.join(__dir__, 'properties.treetop'))
|
38
|
+
# @private
|
39
|
+
class Parser < PropertiesParser; end
|
68
40
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
equal_idx = line.index("=")
|
73
|
-
colon_idx = line.index(":")
|
41
|
+
def parse_doc(content)
|
42
|
+
Parser.new.parse(content)
|
43
|
+
end
|
74
44
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
45
|
+
def render_element(element)
|
46
|
+
if element.is_a? Comment
|
47
|
+
return '' if element.text.nil?
|
48
|
+
comments = element.text.split(/[\r\n]+/)
|
49
|
+
comments.collect do |comment|
|
50
|
+
format("%<type>c %<comment>s\n",
|
51
|
+
type: element.type, comment: comment.strip)
|
52
|
+
end.join
|
53
|
+
elsif element.is_a? Definition
|
54
|
+
key = element.key
|
55
|
+
value = element.value
|
56
|
+
format(%(%<key>s = %<value>s\n),
|
57
|
+
key: escape(key), value: escape(value))
|
82
58
|
end
|
83
|
-
name, value = line.split(/\s*[=:]\s*/, 2)
|
84
|
-
value = value.gsub("\\n", "\n") # convert \n to newlines
|
85
|
-
result[name] = value
|
86
59
|
end
|
87
|
-
result
|
88
60
|
end
|
89
|
-
|
90
61
|
end
|
91
62
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# https://en.wikipedia.org/wiki/.properties
|
2
|
+
grammar Properties
|
3
|
+
rule document
|
4
|
+
(whitespace / comment / definition)* {
|
5
|
+
def content
|
6
|
+
elements.collect { |i| i.content }.select { |i| i[0] != :whitespace }
|
7
|
+
end
|
8
|
+
}
|
9
|
+
end
|
10
|
+
|
11
|
+
rule comment
|
12
|
+
start_comment comment_content end_comment {
|
13
|
+
def content
|
14
|
+
[:comment, elements[1].text_value, elements[0].text_value]
|
15
|
+
end
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
rule start_comment
|
20
|
+
'#' / '!'
|
21
|
+
end
|
22
|
+
|
23
|
+
rule eof
|
24
|
+
!character
|
25
|
+
end
|
26
|
+
|
27
|
+
rule end_comment
|
28
|
+
newline / eof
|
29
|
+
end
|
30
|
+
|
31
|
+
rule comment_content
|
32
|
+
(!end_comment character)+
|
33
|
+
end
|
34
|
+
|
35
|
+
rule definition
|
36
|
+
key assignment value? end_definition {
|
37
|
+
def content
|
38
|
+
[:definition, elements[0].text_value, elements[2] ? elements[2].text_value : nil]
|
39
|
+
end
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
rule end_definition
|
44
|
+
newline / eof
|
45
|
+
end
|
46
|
+
|
47
|
+
rule newline
|
48
|
+
"\n"
|
49
|
+
end
|
50
|
+
|
51
|
+
rule line_continuation
|
52
|
+
"\\" newline whitespace*
|
53
|
+
end
|
54
|
+
|
55
|
+
rule assignment
|
56
|
+
whitespace* ('=' / ':') whitespace*
|
57
|
+
end
|
58
|
+
|
59
|
+
rule character
|
60
|
+
.
|
61
|
+
end
|
62
|
+
|
63
|
+
rule key
|
64
|
+
('\\ ' / !assignment character)+
|
65
|
+
#(!assignment word)+
|
66
|
+
end
|
67
|
+
|
68
|
+
rule value_character
|
69
|
+
line_continuation / character
|
70
|
+
end
|
71
|
+
|
72
|
+
rule word
|
73
|
+
('\\ ' / !assignment character)+
|
74
|
+
end
|
75
|
+
|
76
|
+
rule value
|
77
|
+
(!newline value_character)+
|
78
|
+
end
|
79
|
+
|
80
|
+
rule whitespace
|
81
|
+
[ \t\r\n] {
|
82
|
+
def content
|
83
|
+
[:whitespace, text_value]
|
84
|
+
end
|
85
|
+
}
|
86
|
+
end
|
87
|
+
end
|
@@ -1,51 +1,66 @@
|
|
1
|
-
module Translatomatic
|
2
|
-
|
3
|
-
|
1
|
+
module Translatomatic
|
2
|
+
module ResourceFile
|
3
|
+
# Windows resources file (XML)
|
4
|
+
class RESW < XML
|
5
|
+
# (see Base.extensions)
|
6
|
+
def self.extensions
|
7
|
+
%w[resw resx]
|
8
|
+
end
|
4
9
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
10
|
+
# (see Base.key_value?)
|
11
|
+
def self.key_value?
|
12
|
+
true
|
13
|
+
end
|
9
14
|
|
10
|
-
|
11
|
-
def self.is_key_value?
|
12
|
-
true
|
13
|
-
end
|
15
|
+
private
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
def init_nodemap
|
18
|
+
@nodemap = {}
|
19
|
+
nodes = @doc.search('//data/@name|//text()|//comment()')
|
20
|
+
nodes.each do |node|
|
21
|
+
process_node(node)
|
22
|
+
end
|
23
|
+
end
|
21
24
|
|
22
|
-
|
25
|
+
def process_node(node)
|
26
|
+
if node.comment?
|
27
|
+
@metadata.parse_comment(node.content)
|
28
|
+
elsif node.type == Nokogiri::XML::Node::ATTRIBUTE_NODE # data name=""
|
29
|
+
@key = node.content
|
30
|
+
elsif node.text?
|
31
|
+
process_text_node(node)
|
32
|
+
end
|
33
|
+
end
|
23
34
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
35
|
+
def process_text_node(node)
|
36
|
+
parent = node.parent
|
37
|
+
if parent.name == 'value' # <value>content</value>
|
38
|
+
found_value(node)
|
39
|
+
elsif parent.name == 'comment'
|
40
|
+
@metadata.parse_comment(node.content)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def found_value(value)
|
45
|
+
@nodemap[@key] = value if @key
|
46
|
+
@metadata.assign_key(@key)
|
47
|
+
@key = nil
|
31
48
|
end
|
32
|
-
@nodemap = result
|
33
|
-
end
|
34
49
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
50
|
+
def create_node(key, value)
|
51
|
+
# add xml: <data name="key"><value>value</value></data>
|
52
|
+
data_node = Nokogiri::XML::Node.new('data', @doc)
|
53
|
+
data_node['name'] = key
|
54
|
+
value_node = Nokogiri::XML::Node.new('value', @doc)
|
55
|
+
text_node = Nokogiri::XML::Text.new(value.to_s, @doc)
|
56
|
+
value_node.add_child(text_node)
|
57
|
+
data_node.add_child(value_node)
|
43
58
|
|
44
|
-
|
59
|
+
@doc.root.add_child(data_node)
|
45
60
|
|
46
|
-
|
47
|
-
|
61
|
+
@nodemap[key] = text_node
|
62
|
+
@properties[key] = value
|
63
|
+
end
|
48
64
|
end
|
49
|
-
|
50
|
-
|
51
|
-
end # module
|
65
|
+
end
|
66
|
+
end
|
@@ -1,75 +1,107 @@
|
|
1
|
-
module Translatomatic
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
module Translatomatic
|
2
|
+
module ResourceFile
|
3
|
+
# Subtitle resource file.
|
4
|
+
# requires 'titlekit' gem
|
5
|
+
class Subtitle < Base
|
6
|
+
# (see Base.extensions)
|
7
|
+
def self.extensions
|
8
|
+
%w[srt ass ssa]
|
9
|
+
end
|
5
10
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
11
|
+
# (see Base.enabled?)
|
12
|
+
def self.enabled?
|
13
|
+
@enabled ||= begin
|
14
|
+
require 'titlekit'
|
15
|
+
true
|
16
|
+
rescue LoadError
|
17
|
+
false
|
18
|
+
end
|
19
|
+
end
|
10
20
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
21
|
+
# (see Base#set)
|
22
|
+
def set(key, value)
|
23
|
+
super(key, value)
|
24
|
+
|
25
|
+
if @subtitle_map.include?(key)
|
26
|
+
@subtitle_map[key][:lines] = value.to_s
|
27
|
+
else
|
28
|
+
add_subtitle(lines: value) unless value.blank?
|
29
|
+
end
|
18
30
|
end
|
19
|
-
end
|
20
31
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
@subtitle_map[key][:lines] = value
|
32
|
+
# (see Base#save)
|
33
|
+
def save(target = path, options = {})
|
34
|
+
add_created_by unless options[:no_created_by] || created_by?
|
35
|
+
export(target)
|
26
36
|
end
|
27
|
-
end
|
28
37
|
|
29
|
-
|
30
|
-
def save(target = path, options = {})
|
31
|
-
export(target)
|
32
|
-
end
|
38
|
+
private
|
33
39
|
|
34
|
-
|
40
|
+
def init
|
41
|
+
@subtitle_map = {}
|
42
|
+
@subtitles = []
|
43
|
+
@keynum = 1
|
44
|
+
end
|
35
45
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
46
|
+
def load
|
47
|
+
@metadata.reset
|
48
|
+
subtitles = import(@path)
|
49
|
+
subtitles.each { |i| add_subtitle(i) }
|
50
|
+
init_properties
|
51
|
+
end
|
40
52
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
53
|
+
def process_metadata(key, subtitle)
|
54
|
+
lines = subtitle[:lines] || ''
|
55
|
+
context = @metadata.parse_comment(lines)
|
56
|
+
@metadata.assign_key(key) unless context.present?
|
57
|
+
end
|
46
58
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
59
|
+
def add_created_by
|
60
|
+
# TODO
|
61
|
+
end
|
62
|
+
|
63
|
+
def add_subtitle(subtitle = {})
|
51
64
|
key = "key#{@keynum}"
|
65
|
+
subtitle[:id] ||= @keynum
|
66
|
+
subtitle[:start] ||= @keynum * 10
|
67
|
+
subtitle[:end] ||= @keynum * 10 + 5
|
68
|
+
process_metadata(key, subtitle)
|
52
69
|
@keynum += 1
|
53
70
|
@subtitle_map[key] = subtitle
|
71
|
+
@subtitles << subtitle
|
54
72
|
end
|
55
|
-
end
|
56
73
|
|
57
|
-
|
58
|
-
|
59
|
-
|
74
|
+
# Find the first gap in subtitles with a minimum length in seconds.
|
75
|
+
# @return [Array] [start, end] Start and end times of the gap
|
76
|
+
def find_gap(min_length)
|
77
|
+
last = 0
|
78
|
+
@subtitles.each do |subtitle|
|
79
|
+
return [last, subtitle.start] if subtitle.start - last >= min_length
|
80
|
+
last = subtitle.end
|
81
|
+
end
|
82
|
+
[last, -1]
|
83
|
+
end
|
60
84
|
|
61
|
-
|
62
|
-
|
63
|
-
|
85
|
+
def init_properties
|
86
|
+
@properties = @subtitle_map.transform_values { |i| i[:lines] }
|
87
|
+
end
|
64
88
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
89
|
+
def import(path)
|
90
|
+
contents = read_contents(path)
|
91
|
+
return [] if contents.blank?
|
92
|
+
import_export_class(path).import(contents)
|
93
|
+
end
|
69
94
|
|
70
|
-
|
71
|
-
|
72
|
-
|
95
|
+
def export(target, _options = {})
|
96
|
+
content = import_export_class(target).export(@subtitles) || ''
|
97
|
+
content = content.gsub(/[\r\n]+\Z/, '') + "\n"
|
98
|
+
target.write(content)
|
99
|
+
end
|
100
|
+
|
101
|
+
def import_export_class(path)
|
102
|
+
class_name = path.extname.sub(/^\./, '').upcase
|
103
|
+
Titlekit.const_get(class_name)
|
104
|
+
end
|
73
105
|
end
|
74
106
|
end
|
75
107
|
end
|