こちらをみると、juno's redmine_importer at master - GitHubを使って、簡単インポート!なんてあるので、挑戦。
が、1.0.2だと、なかなか手強かった。
まず、言語別のメッセージファイル(ja.yml)がそのままじゃ使えず。
1つは、ファイルの先頭に言語名を記述、以下の行はインデントを設定する必要がある、と。
もう1つは、ファイルの配置場所。lang/以下にあるファイルは、config/locales/以下に移動する必要あり。
これは、他のpluginとかでも、同様な話かも。
さらにもう1ついじりました。
なぜか、メッセージに対し、複数の変数を渡すと、文句を言ってくるので、メッセージに対し、1つの引数になるよう、メッセージを分割しました。
これらの設定変更で、メッセージはちゃんと、日本語でも表示されました。
次は、1.0.2だから、というわけじゃないと思うんですが、文字コードにしてやられました。
一応、最初の画面で文字コードを選択できるようにはなっているのですが、選んだところで、どうも、正しく動いていない。
いろいろ調べてみると、FasterCSVでファイルを読み込む時に、encodingは渡されているのですが、どうも、機能していない。
いろいろ、トライしてみました。
ファイルの読み込み時に一括してUTF-8に変換して、その文字列をFasterCSVに渡すものの、正しく解析できない模様。
なので、ファイルを読み込んだ後、個々のデータをちまちま変換する方法で。
nkfで文字コード変換を実行しているため、かなりの回数、nkfの実行モジュールが呼び出されていると思われます。
改善しようと思えば、できなくはないと思いますが、まずは動くものを、ということで。
それと、何ででしょうか、nkfのオプションでわざわざ入力の文字コードを指定していたのですが、nkfは、入力の文字コードは自動判定してくれるので、出力をUTF-8にしてね、とすればよいので、結局、最初の画面の文字コード指定は、意味がなくなりました。
まぁ、この文字コードにはやられましたが、動作結果は納得かな。
以下、unified diffを。
インデントがスペースか、tabの違いで、rejectされるかもしれませんので、ご注意を。
----
diff -uNr juno-redmine_importer-9505446/app/controllers/importer_controller.rb redmine_importer/app/controllers/importer_controller.rb
--- juno-redmine_importer-9505446/app/controllers/importer_controller.rb 2010-10-14 18:00:31.000000000 +0900
+++ redmine_importer/app/controllers/importer_controller.rb 2010-10-14 18:05:30.000000000 +0900
@@ -2,13 +2,14 @@
require 'fastercsv'
require 'tempfile'
require 'nkf'
+require 'kconv'
class ImporterController < ApplicationController
unloadable
before_filter :find_project
- ISSUE_ATTRS = [:id, :subject, :assigned_to, :fixed_version,
+ ISSUE_ATTRS = [:identifier, :subject, :assigned_to, :fixed_version,
:author, :description, :category, :priority, :tracker, :status,
:start_date, :due_date, :done_ratio, :estimated_hours]
@@ -48,7 +49,13 @@
i = 0
@samples = []
- FasterCSV.foreach(tmpfile.path, {:headers=>true, :encoding=>encoding, :quote_char=>wrapper, :col_sep=>splitter}) do |row|
+ FasterCSV.foreach(tmpfile.path, {:headers=>true, :encoding=>encoding, :quote_char=>wrapper, :col_sep=>splitter}) do |row_orig|
+
+ row = FasterCSV::Row.new(convert_headers_encoding(row_orig.headers), convert_headers_encoding(row_orig.headers), true)
+ for n in 0..(row.size - 1)
+ row[n] = row_orig[n] != nil ? NKF::nkf('-w', row_orig[n]) : row_orig[n]
+ end
+
@samples[i] = row
i += 1
@@ -58,13 +65,13 @@
end # do
if @samples.size > 0
- @headers = convert_headers_encoding(@samples[0].headers, encoding)
+ @headers = convert_headers_encoding(@samples[0].headers)
end
# fields
@attrs = Array.new
ISSUE_ATTRS.each do |attr|
- @attrs.push([l_has_string?("field_#{attr}".to_sym) ? l("field_#{attr}".to_sym) : attr.to_s.humanize, attr])
+ @attrs.push([l("field_#{attr}".to_sym), attr])
end
@project.all_issue_custom_fields.each do |cfield|
@attrs.push([cfield.name, cfield.name])
@@ -112,7 +119,12 @@
# attrs_map is fields_map's invert
attrs_map = fields_map.invert
- FasterCSV.foreach(tmpfile.path, {:headers=>true, :encoding=>encoding, :quote_char=>wrapper, :col_sep=>splitter}) do |row|
+ FasterCSV.foreach(tmpfile.path, {:headers=>true, :encoding=>encoding, :quote_char=>wrapper, :col_sep=>splitter}) do |row_orig|
+
+ row = FasterCSV::Row.new(convert_headers_encoding(row_orig.headers), convert_headers_encoding(row_orig.headers), true)
+ for n in 0..(row.size - 1)
+ row[n] = row_orig[n] != nil ? NKF::nkf('-w', row_orig[n]) : row_orig[n]
+ end
project = Project.find_by_name(row[attrs_map["project"]])
tracker = Tracker.find_by_name(row[attrs_map["tracker"]])
@@ -121,7 +133,7 @@
priority = Enumeration.find_by_name(row[attrs_map["priority"]])
category = IssueCategory.find_by_name(row[attrs_map["category"]])
assigned_to = User.find_by_login(row[attrs_map["assigned_to"]])
- fixed_version = Version.find_by_name(row[attrs_map["fixed_version"]])
+ fixed_version = Version.find_by_name_and_project_id(row[attrs_map["fixed_version"]], project.id)
# new issue or find exists one
issue = Issue.new
@@ -194,6 +206,7 @@
# project affect
if project == nil
project = Project.find_by_id(issue.project_id)
+ fixed_version = Version.find_by_name_and_project_id(row[attrs_map["fixed_version"]], project.id)
end
@affect_projects_issues.has_key?(project.name) ?
@affect_projects_issues[project.name] += 1 : @affect_projects_issues[project.name] = 1
@@ -236,7 +249,7 @@
if @failed_issues.size > 0
@failed_issues = @failed_issues.sort
- @headers = convert_headers_encoding(@failed_issues[0][1].headers, encoding)
+ @headers = convert_headers_encoding(@failed_issues[0][1].headers)
end
end
@@ -246,11 +259,8 @@
@project = Project.find(params[:project_id])
end
- def convert_headers_encoding(headers, encoding)
- nkf_option = nil
- nkf_option = '-Sw' if encoding == 'S'
- nkf_option = '-Ew' if encoding == 'EUC'
- nkf_option ? headers.map! {|e| NKF.nkf('-m0 -x ' + nkf_option, e)} : headers
+ def convert_headers_encoding(headers)
+ headers.map! {|e| NKF.nkf('-m0 -x -w', e)}
end
end
diff -uNr juno-redmine_importer-9505446/app/views/importer/index.html.erb redmine_importer/app/views/importer/index.html.erb
--- juno-redmine_importer-9505446/app/views/importer/index.html.erb 2010-10-14 18:00:31.000000000 +0900
+++ redmine_importer/app/views/importer/index.html.erb 2010-10-14 13:25:04.000000000 +0900
@@ -8,7 +8,7 @@
<fieldset class="box"><legend><%= l(:label_upload_format) %></legend>
<p><label><%=l(:label_upload_encoding)%></label>
- <%= select_tag "encoding", "<option value=\"U\">UTF8</option><option value=\"EUC\">EUC</option><option value=\"S\">SJIS</option><option value=\"N\">None</option>" %></p>
+ <%= select_tag "encoding", "<option value=\"UTF-8\">UTF8</option><option value=\"EUC-JP\">EUC</option><option value=\"SJIS\">SJIS</option><option value=\"N\">None</option>" %></p>
<p><label><%=l(:label_upload_splitter)%></label>
<%= text_field_tag "splitter", ',', {:size => 3, :maxlength => 1}%></p>
diff -uNr juno-redmine_importer-9505446/app/views/importer/result.html.erb redmine_importer/app/views/importer/result.html.erb
--- juno-redmine_importer-9505446/app/views/importer/result.html.erb 2010-10-14 18:00:31.000000000 +0900
+++ redmine_importer/app/views/importer/result.html.erb 2010-10-14 17:54:33.000000000 +0900
@@ -3,7 +3,7 @@
<% end %>
<h2><%= l(:label_import_result) %></h2>
-<p><%= l(:label_result_notice, @handle_count, @handle_count - @failed_count) %></p>
+<p><%= l(:label_result_notice_f, @handle_count) %><%= l(:label_result_notice_b, @handle_count - @failed_count) %></p>
<p><%= l(:label_result_projects) %><br/>
<% @affect_projects_issues.each do |project, count|%>
<label class="tabular2"><%= project %>:</label><label class="tabular2"><%= l(:label_result_issues, count) %></label><br/>
diff -uNr juno-redmine_importer-9505446/config/locales/en.yml redmine_importer/config/locales/en.yml
--- juno-redmine_importer-9505446/config/locales/en.yml 1970-01-01 09:00:00.000000000 +0900
+++ redmine_importer/config/locales/en.yml 2010-10-13 20:03:39.000000000 +0900
@@ -0,0 +1,35 @@
+en:
+ label_import: "Import"
+ label_issue_importer: "Issue Importer"
+ label_upload_notice: "Select a CSV file to import. Import file must have a header row."
+ label_upload_format: "File format settings"
+ label_upload_encoding: "Encoding:"
+ label_upload_splitter: "Field seperate char:"
+ label_upload_wrapper: "Field wrap char:"
+
+ label_load_rules: "Load saved rules"
+ label_toplines: "Refer to top lines of %s:"
+ label_match_columns: "Matching Columns"
+ label_match_select: "Select match field"
+ label_import_rule: "Import rules"
+ label_default_tracker: "Default tracker:"
+ label_update_issue: "Update exists issue"
+ label_journal_field: "Select field as journal:"
+ label_unique_field: "Select unique field for identify issue:"
+ label_update_other_project: "Allow update issues of other projects"
+ label_ignore_non_exist: "Ignore none exist issues"
+ label_rule_name: "Input rule name"
+
+ label_import_result: "Import Result"
+ label_result_notice: "%d issues processed. %d issues success imported."
+ label_result_notice_f: "%d issues processed. "
+ label_result_notice_b: "%d issues success imported."
+ label_result_projects: "Affected projects:"
+ label_result_issues: "%d issues"
+ label_result_failed: "Failed %d rows:"
+
+ option_ignore: "Ignore"
+
+ button_upload: "Upload File"
+ button_submit: "Submit"
+ button_save_rules_and_submit: "Save match rules and submit"
diff -uNr juno-redmine_importer-9505446/config/locales/ja.yml redmine_importer/config/locales/ja.yml
--- juno-redmine_importer-9505446/config/locales/ja.yml 1970-01-01 09:00:00.000000000 +0900
+++ redmine_importer/config/locales/ja.yml 2010-10-13 14:09:35.000000000 +0900
@@ -0,0 +1,35 @@
+ja:
+ label_import: "インポート"
+ label_issue_importer: "チケットインポーター"
+ label_upload_notice: "インポートするCSVファイルを選択してください。ファイルの最初にはヘッダ行が必要です。"
+ label_upload_format: "ファイル形式の設定"
+ label_upload_encoding: "文字コードエンコーディング:"
+ label_upload_splitter: "フィールド区切り文字:"
+ label_upload_wrapper: "フィールド囲み文字:"
+
+ label_load_rules: "Load saved rules"
+ label_toplines: "%sの先頭:"
+ label_match_columns: "列のマッチング"
+ label_match_select: "対応させるフィールドの選択"
+ label_import_rule: "インポートルール"
+ label_default_tracker: "デフォルトのトラッカー:"
+ label_update_issue: "既存のチケットを更新する"
+ label_journal_field: "履歴として使用するフィールド:"
+ label_unique_field: "チケットの特定に使うユニークなフィールド:"
+ label_update_other_project: "他プロジェクトのチケット更新を許可する"
+ label_ignore_non_exist: "存在しないチケットの指定を無視する"
+ label_rule_name: "ルール名を入力"
+
+ label_import_result: "インポート結果"
+ label_result_notice: "%d 件のチケットを処理し、%d 件のチケットをインポートしました。"
+ label_result_notice_f: "%d 件のチケットを処理し、"
+ label_result_notice_b: "%d 件のチケットをインポートしました。"
+ label_result_projects: "更新したプロジェクト:"
+ label_result_issues: "%d 件"
+ label_result_failed: "%d 個の列が失敗:"
+
+ option_ignore: "無視"
+
+ button_upload: "アップロード"
+ button_submit: "送信"
+ button_save_rules_and_submit: "マッチングルールを保存して次へ"
----
が、1.0.2だと、なかなか手強かった。
まず、言語別のメッセージファイル(ja.yml)がそのままじゃ使えず。
1つは、ファイルの先頭に言語名を記述、以下の行はインデントを設定する必要がある、と。
もう1つは、ファイルの配置場所。lang/以下にあるファイルは、config/locales/以下に移動する必要あり。
これは、他のpluginとかでも、同様な話かも。
さらにもう1ついじりました。
なぜか、メッセージに対し、複数の変数を渡すと、文句を言ってくるので、メッセージに対し、1つの引数になるよう、メッセージを分割しました。
これらの設定変更で、メッセージはちゃんと、日本語でも表示されました。
次は、1.0.2だから、というわけじゃないと思うんですが、文字コードにしてやられました。
一応、最初の画面で文字コードを選択できるようにはなっているのですが、選んだところで、どうも、正しく動いていない。
いろいろ調べてみると、FasterCSVでファイルを読み込む時に、encodingは渡されているのですが、どうも、機能していない。
いろいろ、トライしてみました。
ファイルの読み込み時に一括してUTF-8に変換して、その文字列をFasterCSVに渡すものの、正しく解析できない模様。
なので、ファイルを読み込んだ後、個々のデータをちまちま変換する方法で。
nkfで文字コード変換を実行しているため、かなりの回数、nkfの実行モジュールが呼び出されていると思われます。
改善しようと思えば、できなくはないと思いますが、まずは動くものを、ということで。
それと、何ででしょうか、nkfのオプションでわざわざ入力の文字コードを指定していたのですが、nkfは、入力の文字コードは自動判定してくれるので、出力をUTF-8にしてね、とすればよいので、結局、最初の画面の文字コード指定は、意味がなくなりました。
まぁ、この文字コードにはやられましたが、動作結果は納得かな。
以下、unified diffを。
インデントがスペースか、tabの違いで、rejectされるかもしれませんので、ご注意を。
----
diff -uNr juno-redmine_importer-9505446/app/controllers/importer_controller.rb redmine_importer/app/controllers/importer_controller.rb
--- juno-redmine_importer-9505446/app/controllers/importer_controller.rb 2010-10-14 18:00:31.000000000 +0900
+++ redmine_importer/app/controllers/importer_controller.rb 2010-10-14 18:05:30.000000000 +0900
@@ -2,13 +2,14 @@
require 'fastercsv'
require 'tempfile'
require 'nkf'
+require 'kconv'
class ImporterController < ApplicationController
unloadable
before_filter :find_project
- ISSUE_ATTRS = [:id, :subject, :assigned_to, :fixed_version,
+ ISSUE_ATTRS = [:identifier, :subject, :assigned_to, :fixed_version,
:author, :description, :category, :priority, :tracker, :status,
:start_date, :due_date, :done_ratio, :estimated_hours]
@@ -48,7 +49,13 @@
i = 0
@samples = []
- FasterCSV.foreach(tmpfile.path, {:headers=>true, :encoding=>encoding, :quote_char=>wrapper, :col_sep=>splitter}) do |row|
+ FasterCSV.foreach(tmpfile.path, {:headers=>true, :encoding=>encoding, :quote_char=>wrapper, :col_sep=>splitter}) do |row_orig|
+
+ row = FasterCSV::Row.new(convert_headers_encoding(row_orig.headers), convert_headers_encoding(row_orig.headers), true)
+ for n in 0..(row.size - 1)
+ row[n] = row_orig[n] != nil ? NKF::nkf('-w', row_orig[n]) : row_orig[n]
+ end
+
@samples[i] = row
i += 1
@@ -58,13 +65,13 @@
end # do
if @samples.size > 0
- @headers = convert_headers_encoding(@samples[0].headers, encoding)
+ @headers = convert_headers_encoding(@samples[0].headers)
end
# fields
@attrs = Array.new
ISSUE_ATTRS.each do |attr|
- @attrs.push([l_has_string?("field_#{attr}".to_sym) ? l("field_#{attr}".to_sym) : attr.to_s.humanize, attr])
+ @attrs.push([l("field_#{attr}".to_sym), attr])
end
@project.all_issue_custom_fields.each do |cfield|
@attrs.push([cfield.name, cfield.name])
@@ -112,7 +119,12 @@
# attrs_map is fields_map's invert
attrs_map = fields_map.invert
- FasterCSV.foreach(tmpfile.path, {:headers=>true, :encoding=>encoding, :quote_char=>wrapper, :col_sep=>splitter}) do |row|
+ FasterCSV.foreach(tmpfile.path, {:headers=>true, :encoding=>encoding, :quote_char=>wrapper, :col_sep=>splitter}) do |row_orig|
+
+ row = FasterCSV::Row.new(convert_headers_encoding(row_orig.headers), convert_headers_encoding(row_orig.headers), true)
+ for n in 0..(row.size - 1)
+ row[n] = row_orig[n] != nil ? NKF::nkf('-w', row_orig[n]) : row_orig[n]
+ end
project = Project.find_by_name(row[attrs_map["project"]])
tracker = Tracker.find_by_name(row[attrs_map["tracker"]])
@@ -121,7 +133,7 @@
priority = Enumeration.find_by_name(row[attrs_map["priority"]])
category = IssueCategory.find_by_name(row[attrs_map["category"]])
assigned_to = User.find_by_login(row[attrs_map["assigned_to"]])
- fixed_version = Version.find_by_name(row[attrs_map["fixed_version"]])
+ fixed_version = Version.find_by_name_and_project_id(row[attrs_map["fixed_version"]], project.id)
# new issue or find exists one
issue = Issue.new
@@ -194,6 +206,7 @@
# project affect
if project == nil
project = Project.find_by_id(issue.project_id)
+ fixed_version = Version.find_by_name_and_project_id(row[attrs_map["fixed_version"]], project.id)
end
@affect_projects_issues.has_key?(project.name) ?
@affect_projects_issues[project.name] += 1 : @affect_projects_issues[project.name] = 1
@@ -236,7 +249,7 @@
if @failed_issues.size > 0
@failed_issues = @failed_issues.sort
- @headers = convert_headers_encoding(@failed_issues[0][1].headers, encoding)
+ @headers = convert_headers_encoding(@failed_issues[0][1].headers)
end
end
@@ -246,11 +259,8 @@
@project = Project.find(params[:project_id])
end
- def convert_headers_encoding(headers, encoding)
- nkf_option = nil
- nkf_option = '-Sw' if encoding == 'S'
- nkf_option = '-Ew' if encoding == 'EUC'
- nkf_option ? headers.map! {|e| NKF.nkf('-m0 -x ' + nkf_option, e)} : headers
+ def convert_headers_encoding(headers)
+ headers.map! {|e| NKF.nkf('-m0 -x -w', e)}
end
end
diff -uNr juno-redmine_importer-9505446/app/views/importer/index.html.erb redmine_importer/app/views/importer/index.html.erb
--- juno-redmine_importer-9505446/app/views/importer/index.html.erb 2010-10-14 18:00:31.000000000 +0900
+++ redmine_importer/app/views/importer/index.html.erb 2010-10-14 13:25:04.000000000 +0900
@@ -8,7 +8,7 @@
<fieldset class="box"><legend><%= l(:label_upload_format) %></legend>
<p><label><%=l(:label_upload_encoding)%></label>
- <%= select_tag "encoding", "<option value=\"U\">UTF8</option><option value=\"EUC\">EUC</option><option value=\"S\">SJIS</option><option value=\"N\">None</option>" %></p>
+ <%= select_tag "encoding", "<option value=\"UTF-8\">UTF8</option><option value=\"EUC-JP\">EUC</option><option value=\"SJIS\">SJIS</option><option value=\"N\">None</option>" %></p>
<p><label><%=l(:label_upload_splitter)%></label>
<%= text_field_tag "splitter", ',', {:size => 3, :maxlength => 1}%></p>
diff -uNr juno-redmine_importer-9505446/app/views/importer/result.html.erb redmine_importer/app/views/importer/result.html.erb
--- juno-redmine_importer-9505446/app/views/importer/result.html.erb 2010-10-14 18:00:31.000000000 +0900
+++ redmine_importer/app/views/importer/result.html.erb 2010-10-14 17:54:33.000000000 +0900
@@ -3,7 +3,7 @@
<% end %>
<h2><%= l(:label_import_result) %></h2>
-<p><%= l(:label_result_notice, @handle_count, @handle_count - @failed_count) %></p>
+<p><%= l(:label_result_notice_f, @handle_count) %><%= l(:label_result_notice_b, @handle_count - @failed_count) %></p>
<p><%= l(:label_result_projects) %><br/>
<% @affect_projects_issues.each do |project, count|%>
<label class="tabular2"><%= project %>:</label><label class="tabular2"><%= l(:label_result_issues, count) %></label><br/>
diff -uNr juno-redmine_importer-9505446/config/locales/en.yml redmine_importer/config/locales/en.yml
--- juno-redmine_importer-9505446/config/locales/en.yml 1970-01-01 09:00:00.000000000 +0900
+++ redmine_importer/config/locales/en.yml 2010-10-13 20:03:39.000000000 +0900
@@ -0,0 +1,35 @@
+en:
+ label_import: "Import"
+ label_issue_importer: "Issue Importer"
+ label_upload_notice: "Select a CSV file to import. Import file must have a header row."
+ label_upload_format: "File format settings"
+ label_upload_encoding: "Encoding:"
+ label_upload_splitter: "Field seperate char:"
+ label_upload_wrapper: "Field wrap char:"
+
+ label_load_rules: "Load saved rules"
+ label_toplines: "Refer to top lines of %s:"
+ label_match_columns: "Matching Columns"
+ label_match_select: "Select match field"
+ label_import_rule: "Import rules"
+ label_default_tracker: "Default tracker:"
+ label_update_issue: "Update exists issue"
+ label_journal_field: "Select field as journal:"
+ label_unique_field: "Select unique field for identify issue:"
+ label_update_other_project: "Allow update issues of other projects"
+ label_ignore_non_exist: "Ignore none exist issues"
+ label_rule_name: "Input rule name"
+
+ label_import_result: "Import Result"
+ label_result_notice: "%d issues processed. %d issues success imported."
+ label_result_notice_f: "%d issues processed. "
+ label_result_notice_b: "%d issues success imported."
+ label_result_projects: "Affected projects:"
+ label_result_issues: "%d issues"
+ label_result_failed: "Failed %d rows:"
+
+ option_ignore: "Ignore"
+
+ button_upload: "Upload File"
+ button_submit: "Submit"
+ button_save_rules_and_submit: "Save match rules and submit"
diff -uNr juno-redmine_importer-9505446/config/locales/ja.yml redmine_importer/config/locales/ja.yml
--- juno-redmine_importer-9505446/config/locales/ja.yml 1970-01-01 09:00:00.000000000 +0900
+++ redmine_importer/config/locales/ja.yml 2010-10-13 14:09:35.000000000 +0900
@@ -0,0 +1,35 @@
+ja:
+ label_import: "インポート"
+ label_issue_importer: "チケットインポーター"
+ label_upload_notice: "インポートするCSVファイルを選択してください。ファイルの最初にはヘッダ行が必要です。"
+ label_upload_format: "ファイル形式の設定"
+ label_upload_encoding: "文字コードエンコーディング:"
+ label_upload_splitter: "フィールド区切り文字:"
+ label_upload_wrapper: "フィールド囲み文字:"
+
+ label_load_rules: "Load saved rules"
+ label_toplines: "%sの先頭:"
+ label_match_columns: "列のマッチング"
+ label_match_select: "対応させるフィールドの選択"
+ label_import_rule: "インポートルール"
+ label_default_tracker: "デフォルトのトラッカー:"
+ label_update_issue: "既存のチケットを更新する"
+ label_journal_field: "履歴として使用するフィールド:"
+ label_unique_field: "チケットの特定に使うユニークなフィールド:"
+ label_update_other_project: "他プロジェクトのチケット更新を許可する"
+ label_ignore_non_exist: "存在しないチケットの指定を無視する"
+ label_rule_name: "ルール名を入力"
+
+ label_import_result: "インポート結果"
+ label_result_notice: "%d 件のチケットを処理し、%d 件のチケットをインポートしました。"
+ label_result_notice_f: "%d 件のチケットを処理し、"
+ label_result_notice_b: "%d 件のチケットをインポートしました。"
+ label_result_projects: "更新したプロジェクト:"
+ label_result_issues: "%d 件"
+ label_result_failed: "%d 個の列が失敗:"
+
+ option_ignore: "無視"
+
+ button_upload: "アップロード"
+ button_submit: "送信"
+ button_save_rules_and_submit: "マッチングルールを保存して次へ"
----