modpack_localizer 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.
@@ -0,0 +1,158 @@
1
+ require "zip"
2
+ require "json"
3
+ require "countries"
4
+ require "iso-639"
5
+
6
+ module ModpackLocalizer
7
+ module JAR
8
+ # .jarファイルから言語ファイルの内容とメタデータを抽出するクラス
9
+ class Reader
10
+ # 例: ja_jp
11
+ LOCALE_CODE_REGEX = /\A[a-z]{2,3}_[a-z]{2,3}\z/
12
+
13
+ # performerに渡すレスポンス
14
+ #
15
+ # @param [Boolean] need_translation 翻訳が必要か
16
+ # @param [Hash] json 言語ファイルの内容
17
+ # @param [String] file_name ファイル名
18
+ # @param [String] locale_code ロケールコード
19
+ # @param [String] mod_name mod名
20
+ # @return [LangData]
21
+ LangData = Struct.new(
22
+ :need_translation, :json, :file_name, :locale_code, :mod_name
23
+ )
24
+
25
+ # locale_codeが渡された場合、languageとcountry_nameは不要
26
+ #
27
+ # @param [String] file_path ファイルのパス
28
+ # @param [String] language 言語
29
+ # @param [String] country_name 国
30
+ # @param [String] locale_code ロケールコード
31
+ # @return [ModpackLocalizer::JAR::Reader]
32
+ def initialize(file_path, language, country_name, locale_code)
33
+ @file_path, @language, @country_name = file_path, language, country_name
34
+ @locale_code =
35
+ locale_code&.downcase || make_locale_code(get_language_code(language), get_country_code(country_name))
36
+ # 引数としてlocale_codeが渡された時はチェックしない
37
+ # brb(Netherlands)のような、正規表現にマッチしないlocale_codeが存在するため(brbはISO 639-3でqbr_NL)
38
+ validate_locale_code(@locale_code) unless locale_code
39
+ end
40
+
41
+ # 言語ファイルの内容とメタデータを抽出する
42
+ #
43
+ # @return [LangData] 言語ファイルの内容とメタデータ
44
+ # @raise [ModpackLocalizer::InvalidRegionCodeError] locale_codeが不正な場合
45
+ def extract_lang_json_and_meta_data
46
+ Zip::File.open(@file_path) do |jar|
47
+ # 対象の言語ファイルが存在する場合は翻訳が必要ない
48
+ target_lang_file = find_lang_json(jar, @locale_code)
49
+ if target_lang_file
50
+ return LangData.new(
51
+ false, {}, target_lang_file, nil, extract_mod_name(target_lang_file)
52
+ )
53
+ end
54
+
55
+ lang_file = find_lang_json(jar, "en_us")
56
+ raw_json = JSON.parse(lang_file.get_input_stream.read)
57
+
58
+ LangData.new(
59
+ true, except_comment(raw_json), lang_file, @locale_code, extract_mod_name(lang_file)
60
+ )
61
+ end
62
+ end
63
+
64
+ # フルパスからファイル名を抽出する
65
+ #
66
+ # @param [Zip::Entry] file ファイル
67
+ # @return [String] ファイル名
68
+ def extract_file_name(file)
69
+ file.name.split("/").last
70
+ end
71
+
72
+ private
73
+
74
+ # ロケールコードのバリデーション
75
+ #
76
+ # @param [String] locale_code ロケールコード
77
+ # @return [Boolean]
78
+ def validate_locale_code(locale_code)
79
+ return if locale_code.match(LOCALE_CODE_REGEX)
80
+
81
+ raise ModpackLocalizer::InvalidRegionCodeError.new(locale_code)
82
+ end
83
+
84
+ # .jar内の言語ファイルを取得する
85
+ #
86
+ # @param [Zip::File] opened_jar .jarファイル
87
+ # @param [String] locale_code ロケールコード
88
+ # @return [Zip::Entry] 言語ファイル
89
+ def find_lang_json(opened_jar, locale_code)
90
+ lang_files = opened_jar.glob("**/lang/*.json")
91
+
92
+ lang_files.find { |entry| target_locale_file?(entry, locale_code) }
93
+ end
94
+
95
+ # JSONからコメントを除外する
96
+ #
97
+ # @param [Hash] hash JSONのハッシュ
98
+ # @return [Hash] コメントを除外したハッシュ
99
+ def except_comment(hash)
100
+ hash.except("_comment")
101
+ end
102
+
103
+ # 対象の言語ファイルかどうか
104
+ #
105
+ # @param [Zip::Entry] file ファイル
106
+ # @param [String] locale_code ロケールコード
107
+ # @return [Boolean]
108
+ def target_locale_file?(file, locale_code)
109
+ file_name = extract_file_name(file)
110
+
111
+ file_name.include?("#{locale_code}.json")
112
+ end
113
+
114
+ # フルパスからmod名を抽出する
115
+ #
116
+ # @param [Zip::Entry] file ファイル
117
+ # @return [String] mod名
118
+ def extract_mod_name(file)
119
+ file.name.split("/").last(3).first
120
+ end
121
+
122
+ # ロケールコードを生成する
123
+ #
124
+ # @param [String] lang_code 言語コード
125
+ # @param [String] country_code 国コード
126
+ # @return [String] ロケールコード
127
+ def make_locale_code(lang_code, country_code)
128
+ "#{lang_code}_#{country_code}"
129
+ end
130
+
131
+ # 言語名から言語コードを取得する
132
+ #
133
+ # @param [String] language_name 言語名
134
+ # @return [String] 言語コード
135
+ def get_language_code(language_name)
136
+ result = ISO_639.find_by_english_name(optimize(language_name))
137
+ result&.alpha2&.downcase || result&.alpha3&.downcase
138
+ end
139
+
140
+ # 国名から国コードを取得する
141
+ #
142
+ # @param [String] country_name 国名
143
+ # @return [String] 国コード
144
+ def get_country_code(country_name)
145
+ result = ISO3166::Country.find_country_by_any_name(optimize(country_name))
146
+ result&.alpha2&.downcase || result&.alpha3&.downcase
147
+ end
148
+
149
+ # ISO関連のgemが受け付けられる形式に変換
150
+ #
151
+ # @param [String] str 文字列
152
+ # @return [String] 変換後の文字列
153
+ def optimize(str)
154
+ str.gsub("_", " ").split.map(&:capitalize).join(" ")
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,121 @@
1
+ require "zip"
2
+
3
+ module ModpackLocalizer
4
+ module JAR
5
+ # .jarファイルを翻訳してリソースパックを作成するクラス
6
+ class Writer
7
+ # 1.19.2
8
+ PACK_FORMAT = 9
9
+
10
+ # @return [ModpackLocalizer::JAR::Writer]
11
+ def initialize
12
+ @output_path_base = "output/mods/modpack_localizer"
13
+ @output_path = nil
14
+ end
15
+
16
+ # リソースパックを作成する
17
+ #
18
+ # @param [ModpackLocalizer::JAR::Reader::LangData] results 言語ファイルの内容とメタデータ
19
+ # @return [void]
20
+ def make_resource_pack(results)
21
+ results.file_name = replace_default_locale_code(results.file_name.name, results.locale_code)
22
+ @output_path = merge_base_path(results.file_name)
23
+
24
+ make_file(@output_path, results.json)
25
+ mcmeta_info = mcmeta(PACK_FORMAT, results.locale_code)
26
+ make_file(mcmeta_info[:file_path], mcmeta_info[:meta_data])
27
+
28
+ zipping_resource_pack
29
+ end
30
+
31
+ # zipにする前に作成したリソースパックを削除する
32
+ # return [void]
33
+ def remove_before_zipping_directory
34
+ FileUtils.rm_rf(@output_path_base)
35
+ end
36
+
37
+ private
38
+
39
+ # ファイル名のロケールコードを指定のロケールコードに置き換える
40
+ #
41
+ # @param [String] file_name ファイル名
42
+ # @param [String] locale_code ロケールコード
43
+ # @return [String] ロケールコードが置き換わったファイル名
44
+ def replace_default_locale_code(file_name, locale_code)
45
+ file_name.gsub("en_us", locale_code)
46
+ end
47
+
48
+ # ファイルの出力先のパスを生成する
49
+ #
50
+ # @param [String] file_name ファイル名
51
+ # @return [String] ファイルの出力先のパス
52
+ def merge_base_path(file_name)
53
+ "#{@output_path_base}/#{file_name}"
54
+ end
55
+
56
+ # ファイルを作成する
57
+ #
58
+ # @param [String] path ファイルのパス
59
+ # @param [Hash] data ファイルに書き込むデータ
60
+ # @return [void]
61
+ def make_file(path, data = nil)
62
+ expand_path = File.expand_path(path)
63
+ dir_path = File.dirname(expand_path)
64
+
65
+ FileUtils.mkdir_p(dir_path) unless File.directory?(dir_path)
66
+
67
+ File.open(expand_path, "w") do |file|
68
+ file.puts(data.nil? ? "" : JSON.pretty_generate(data))
69
+ end
70
+ end
71
+
72
+ # rubocop:disable Lint/SymbolConversion
73
+ # pack.mcmetaを作成するための情報
74
+ #
75
+ # @param [Integer] pack_format リソースパックのバージョン
76
+ # @param [String] locale_code ロケールコード
77
+ # @return [Hash] pack.mcmetaの情報
78
+ def mcmeta(pack_format, locale_code)
79
+ meta_data = {
80
+ "pack": {
81
+ "pack_format": pack_format,
82
+ "description": "Localized for #{locale_code} by ModpackLocalizer"
83
+ }
84
+ }
85
+
86
+ file_path = "#{@output_path_base}/pack.mcmeta"
87
+ { file_path: file_path, meta_data: meta_data }
88
+ end
89
+ # rubocop:enable Lint/SymbolConversion
90
+
91
+ # リソースパックをzipにする
92
+ #
93
+ # @return [void]
94
+ def zipping_resource_pack
95
+ Zip::File.open("#{@output_path_base}.zip", create: true) do |zip|
96
+ extract_inner_files { |file| add_file_to_zip(zip, file) }
97
+ end
98
+ end
99
+
100
+ # ディレクトリ内のファイルをzipに追加する
101
+ #
102
+ # @yield [String] file ファイル
103
+ # @return [void]
104
+ def extract_inner_files(&block)
105
+ Dir.glob("#{@output_path_base}/**/*").each do |file|
106
+ block.call(file)
107
+ end
108
+ end
109
+
110
+ # ファイルをzipに追加する
111
+ #
112
+ # @param [Zip::File] zip zipファイル
113
+ # @param [String] file ファイル
114
+ # @return [void]
115
+ def add_file_to_zip(zip, file)
116
+ entry_name = file.sub("#{@output_path_base}/", "")
117
+ zip.add(entry_name, file) unless zip.find_entry(entry_name)
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,118 @@
1
+ require_relative "../util/indent_helper"
2
+
3
+ module ModpackLocalizer
4
+ module SNBT
5
+ # SNBT形式のファイルからdescription: ["some description"]を抽出するモジュール
6
+ module DescriptionExtractor
7
+ include IndentHelper
8
+
9
+ # description: ["some description"]を抽出する
10
+ #
11
+ # @param [String] file_path ファイルのパス
12
+ # @return [Array<Hash>] 説明、開始行番号、終了行番号の配列
13
+ def extract_descriptions(file_path)
14
+ lines = File.readlines(file_path)
15
+ extract_from_file(lines)
16
+ end
17
+
18
+ private
19
+
20
+ # ファイルから説明を抽出する
21
+ #
22
+ # @param [Array<String>] lines 行の配列
23
+ # @return [Array<Hash>] 説明、開始行番号、終了行番号、インデントのハッシュの配列
24
+ def extract_from_file(lines)
25
+ descs = []
26
+ desc_content = []
27
+ start_line = nil
28
+
29
+ lines.each_with_index do |line, index|
30
+ indent = count_indent(line)
31
+
32
+ # 1行の説明の場合はそのままハッシュに変換
33
+ # 複数行の場合は、開始行と終了行の間の説明を抽出する
34
+ if oneline?(line)
35
+ descs << build_oneline(line, index, indent)
36
+ elsif start_line?(line)
37
+ start_line = index
38
+ elsif middle_line?(line, start_line)
39
+ desc_content << line.strip
40
+ elsif end_line?(line, start_line)
41
+ descs << build_multiline(desc_content, start_line, index, indent)
42
+ start_line = nil
43
+ desc_content = []
44
+ end
45
+ end
46
+
47
+ descs
48
+ end
49
+
50
+ # 1行かどうか
51
+ #
52
+ # @param [String] line 行
53
+ # @return [Boolean]
54
+ def oneline?(line)
55
+ oneline_description?(line)
56
+ end
57
+
58
+ # 開始行かどうか
59
+ #
60
+ # @param [String] line 行
61
+ # @return [Boolean]
62
+ def start_line?(line)
63
+ start_of?(line, key: :description)
64
+ end
65
+
66
+ # 終了行かどうか
67
+ #
68
+ # @param [String] line 行
69
+ # @param [Integer] start_line 開始行番号
70
+ # @return [Boolean]
71
+ def end_line?(line, start_line)
72
+ line.strip.end_with?("]") && start_line
73
+ end
74
+
75
+ # 中間行かどうか
76
+ #
77
+ # @param [String] line 行
78
+ # @param [Integer] start_line 開始行番号
79
+ # @return [Boolean]
80
+ def middle_line?(line, start_line)
81
+ line.strip != "]" && start_line
82
+ end
83
+
84
+ # 1行の処理
85
+ #
86
+ # @param [String] line 行
87
+ # @param [Integer] index 行番号
88
+ # @param [Integer] indent インデント
89
+ # @return [Hash] 説明、開始行番号、終了行番号、インデントのハッシュ
90
+ def build_oneline(line, index, indent)
91
+ {
92
+ type: :description,
93
+ text: extract_oneline(line, is_desc: true),
94
+ start_line: index,
95
+ end_line: index,
96
+ indent: indent
97
+ }
98
+ end
99
+
100
+ # 複数行の処理
101
+ #
102
+ # @param [Array<String>] content 説明の配列
103
+ # @param [Integer] start_line 開始行番号
104
+ # @param [Integer] index 行番号
105
+ # @param [Integer] indent インデント
106
+ # @return [Hash] 説明、開始行番号、終了行番号、インデントのハッシュ
107
+ def build_multiline(content, start_line, index, indent)
108
+ {
109
+ type: :description,
110
+ text: content.join("\n"),
111
+ start_line: start_line,
112
+ end_line: index,
113
+ indent: indent
114
+ }
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,196 @@
1
+ require_relative "../util/indent_helper"
2
+
3
+ module ModpackLocalizer
4
+ module SNBT
5
+ # 翻訳された内容をSNBT形式に整形するクラス
6
+ class Formatter
7
+ include IndentHelper
8
+
9
+ # 保存できるように整形
10
+ #
11
+ # @param [Hash] content コンテンツ
12
+ # @param [String] indent インデント
13
+ # @return [String] SNBT形式に整形したコンテンツ
14
+ def format_overwritable_lines(content, indent)
15
+ full_lines = adjust_line_length(content)
16
+ format_for_snbt(full_lines, indent, content)
17
+ end
18
+
19
+ # SNBT形式に整形
20
+ #
21
+ # @param [Array<String>] lines 行
22
+ # @param [String] indent インデント
23
+ # @param [Hash] content コンテンツ
24
+ # @return [String] SNBT形式に整形した行
25
+ def format_for_snbt(lines, indent, content)
26
+ lines = prepare_lines_for_snbt(lines, content)
27
+ formatted_lines = format_lines(lines, indent, content)
28
+ "#{indent}#{content[:type]}: #{formatted_lines}"
29
+ end
30
+
31
+ # 行数をstart_line~end_lineと一致させる
32
+ #
33
+ # @param [Hash] content コンテンツ
34
+ # @return [void]
35
+ def adjust_line_length(content)
36
+ required_lines = extract_required_line_counts(content)
37
+ lines = content[:text].split("\n")
38
+
39
+ delete_over_lines(lines, required_lines)
40
+ add_missing_lines(lines, required_lines, content[:indent])
41
+
42
+ lines
43
+ end
44
+
45
+ private
46
+
47
+ # 不要な文字を削除する
48
+ #
49
+ # @param [String] lines 行
50
+ # @param [Hash] content コンテンツ
51
+ # @return [Array<String>] 不要な文字を削除した行
52
+ def prepare_lines_for_snbt(lines, content)
53
+ lines.map! { |line| delete_unwanted_symbols(line) }
54
+ lines.map!(&:strip) unless content[:type] == :description
55
+ lines
56
+ end
57
+
58
+ # SNBT形式に変換しやすい形に整形
59
+ #
60
+ # @param [Array<String>] lines 行
61
+ # @param [String] indent インデント
62
+ # @param [Hash] content コンテンツ
63
+ # @return [String] SNBT形式に変換しやすく整形した行
64
+ def format_lines(lines, indent, content)
65
+ if lines.length == 1
66
+ content[:type] == :description ? "[#{lines[0].strip}]" : lines[0].strip.to_s
67
+ else
68
+ # [
69
+ # "Hello"
70
+ # "World"
71
+ # ]
72
+ mid_indent = middle_indent(content[:indent])
73
+ lines = lines.map { |line| "#{mid_indent}#{line.strip}" }
74
+ "[\n#{lines.join("\n")}\n#{indent}]"
75
+ end
76
+ end
77
+
78
+ # 必要な行数を抽出
79
+ #
80
+ # @param [Hash] content コンテンツ
81
+ # @return [Integer] 必要な行数
82
+ def extract_required_line_counts(content)
83
+ # start_lineが1、end_lineが5の場合、必要な行数はブラケットを抜いて3行
84
+ # そのため、(end(5) - start(1)) + 1行 - ブラケット2行 = 3行となる
85
+ line_offset, without_brackets = 1, 2
86
+
87
+ (content[:end_line] - content[:start_line]) + line_offset - without_brackets
88
+ end
89
+
90
+ # 不要な行を削除
91
+ #
92
+ # @param [Array<String>] lines 行
93
+ # @param [Integer] required_lines 必要な行数
94
+ # @return [void]
95
+ def delete_over_lines(lines, required_lines)
96
+ return unless lines.length > required_lines
97
+
98
+ gap_length = lines.length - required_lines
99
+ gap_length.times do
100
+ index = lines.index("")
101
+ lines.delete_at(index) if index
102
+ end
103
+ end
104
+
105
+ # 不足している行を追加
106
+ #
107
+ # @param [Array<String>] lines 行
108
+ # @param [Integer] required_lines 必要な行数
109
+ # @param [String] indent インデント
110
+ # @return [void]
111
+ def add_missing_lines(lines, required_lines, indent)
112
+ return unless lines.length < required_lines
113
+
114
+ while lines.length < required_lines
115
+ lines << empty_middle_line(indent)
116
+ end
117
+ end
118
+
119
+ # 中間行の空行を作成
120
+ #
121
+ # @return [String] 空行
122
+ def empty_middle_line(indent)
123
+ middle_indent(indent).to_s
124
+ end
125
+
126
+ # 不要な記号を削除
127
+ #
128
+ # @param [String] line 行
129
+ # @return [String] 不要な記号を削除した行
130
+ def delete_unwanted_symbols(line)
131
+ line = delete_backslash(line)
132
+ line = delete_semicolon(line)
133
+ line = delete_dup_quotes(line)
134
+ line = delete_jp_quotes(line)
135
+ delete_curved_quotes(line)
136
+ end
137
+
138
+ # 不要なバックスラッシュを削除
139
+ #
140
+ # @param [String] line 行
141
+ # @return [String] 不要なバックスラッシュを削除した行
142
+ def delete_backslash(line)
143
+ line.gsub("\\", "")
144
+ end
145
+
146
+ # 不要なセミコロンを削除
147
+ #
148
+ # @param [String] line 行
149
+ # @return [String] 不要なセミコロンを削除した行
150
+ def delete_semicolon(line)
151
+ line.gsub(";", "")
152
+ end
153
+
154
+ # 不要なダブルクオートを削除
155
+ #
156
+ # @param [String] line 行
157
+ # @return [String] 不要なダブルクオートを削除した行
158
+ def delete_dup_quotes(line)
159
+ # 行間にある余計なダブルクオートを削除するため、一度全てのダブルクオートを削除している
160
+ # 全て削除したあと、行頭、行末にダブルクオートを追加する
161
+ line = line.gsub('"', "")
162
+ line_start = /^(\s*)/
163
+ line = line.sub(line_start, "\"")
164
+ "#{line}\""
165
+ end
166
+
167
+ # 不要な鍵括弧を削除
168
+ #
169
+ # @param [String] line 行
170
+ # @return [String] 不要な鍵括弧を削除した行
171
+ def delete_jp_quotes(line)
172
+ # 「Hello」
173
+ deletable_reg = /「.*」/
174
+ return line unless line.match?(deletable_reg)
175
+
176
+ jp_quotes = [/「/, /」/]
177
+ jp_quotes.each { |quo| line = line.gsub(quo, "") }
178
+ line
179
+ end
180
+
181
+ # 不要な曲がった引用符を削除
182
+ #
183
+ # @param [String] line 行
184
+ # @return [String] 不要な曲がった引用符を削除した行
185
+ def delete_curved_quotes(line)
186
+ # “Hello”
187
+ deletable_reg = /“.*”/
188
+ return line unless line.match?(deletable_reg)
189
+
190
+ curved_quotes = [/“/, /”/]
191
+ curved_quotes.each { |quo| line = line.gsub(quo, "") }
192
+ line
193
+ end
194
+ end
195
+ end
196
+ end
@@ -0,0 +1,92 @@
1
+ require "jp_translator_from_gpt"
2
+ require_relative "../util/help"
3
+ require_relative "../util/error"
4
+ require_relative "reader"
5
+ require_relative "writer"
6
+
7
+ module ModpackLocalizer
8
+ module SNBT
9
+ # .snbtの翻訳を実行するクラス
10
+ # JpTranslatorFromGptを使用して翻訳を行う
11
+ class Performer
12
+ # @param [Boolean] output_logs APIのログを出力するか
13
+ # @param [Array<String>] except_words 翻訳しない単語
14
+ # @param [String] language 言語
15
+ # @param [Boolean] display_help ヘルプを表示するか
16
+ # @return [ModpackLocalizer::SNBT::Performer]
17
+ def initialize(output_logs: true, except_words: [], language: "Japanese", display_help: true)
18
+ @translator = JpTranslatorFromGpt::Translator.new(
19
+ output_logs: output_logs,
20
+ except_words: except_words,
21
+ exchange_language: language
22
+ )
23
+ @reader, @writer, @progress_bar, @loggable = nil
24
+
25
+ ModpackLocalizer.help if display_help
26
+ end
27
+
28
+ # .snbtファイルを翻訳して出力する
29
+ #
30
+ # @param [String] file_path ファイルのパス
31
+ # @param [Boolean] loggable 翻訳ログを出力するか
32
+ # @return [void]
33
+ def perform(file_path, loggable: true)
34
+ @loggable = loggable
35
+ file_path = File.expand_path(file_path)
36
+ validate_path(file_path)
37
+
38
+ @reader, @writer = ModpackLocalizer::SNBT::Reader.new(file_path), ModpackLocalizer::SNBT::Writer.new(file_path)
39
+ results = @reader.extract_all.flatten
40
+ init_progress_bar(file_path, results.length) if @loggable
41
+
42
+ results.each do |result|
43
+ result[:text] = @translator.translate(result[:text])
44
+ @writer.overwrites(result)
45
+ @progress_bar.increment if @loggable
46
+ end
47
+
48
+ puts "Quest translation completed!"
49
+ end
50
+
51
+ # ディレクトリ内の.snbtファイルを翻訳して出力する
52
+ #
53
+ # @param [String] dir_path ディレクトリのパス
54
+ # @param [Boolean] loggable 翻訳ログを出力するか
55
+ # @return [void]
56
+ def perform_directory(dir_path: "quests", loggable: true)
57
+ puts "Performing directory: #{dir_path}" unless loggable
58
+ dir_path = File.expand_path(dir_path)
59
+ validate_path(dir_path)
60
+
61
+ # **でサブディレクトリも含めて取得
62
+ snbt_files = Dir.glob("#{dir_path}/**/*.snbt")
63
+ if snbt_files.empty?
64
+ puts "SNBT files not found in: #{dir_path}"
65
+ return
66
+ end
67
+
68
+ snbt_files.each { |file_path| perform(file_path, loggable: loggable) }
69
+ end
70
+
71
+ # ファイルの存在性のバリデーション
72
+ #
73
+ # @param [String] path ファイルのパス
74
+ # @return [void]
75
+ def validate_path(path)
76
+ path = File.expand_path(path)
77
+ raise ModpackLocalizer::PathNotFoundError.new(path) unless File.exist?(path)
78
+ end
79
+
80
+ private
81
+
82
+ # プログレスバーを初期化する
83
+ #
84
+ # @param [String] file_path ファイルのパス
85
+ # @param [Integer] length プログレスバーの長さ
86
+ # @return [void]
87
+ def init_progress_bar(file_path, length)
88
+ @progress_bar = ModpackLocalizer.create_progress_bar(file_path, length)
89
+ end
90
+ end
91
+ end
92
+ end