Instantly share code, notes, and snippets.

Embed
What would you like to do?
スプレッドシートからRailsの翻訳ファイルを自動生成🙏
# https://github.com/gimite/google-drive-ruby#example-to-readwrite-spreadsheets
class GoogleSpreadsheet
include Singleton
def initialize
session = GoogleDrive::Session.from_config("#{File.dirname(__FILE__)}/google_api/client_secret.json")
@worksheets = session.spreadsheet_by_key(ENV["SPREADSHEET_ID"]).worksheets
end
# すべてのシートの各値を取得
def sheets_values
sheets_values = []
@worksheets.each_with_index do |worksheet, i|
next if i == 0 # 一番初めのシートはREADMEなので飛ばすように
header_rows = 3 # key, ja, en が始まるまでの列数
all_key_values = worksheet.rows(header_rows) # [[key_1, ja_1, en_1, comment_1], [key_2, ja_2, en_2, comment_2]...]
controller = worksheet[2, 2]
action = worksheet[2, 3]
ja_key_values = all_key_values.map { |t| t.values_at(0, 1) }
en_key_values = all_key_values.map { |t| t.values_at(0, 2) }
sheet_values = {
# アプリケーション内で共通で使うものは以下のようになる
# controller: common
# action: (view|mail)
controller: controller,
action: action,
ja: ja_key_values,
en: en_key_values,
}
sheets_values << sheet_values
end
sheets_values
end
end
namespace :locale_generator do
task run: :environment do
start_text = "[#{Rails.env}] locale_generator start"
Rails.logger.info(start_text)
LocaleGenerator.generate
finish_text = "[#{Rails.env}] locale_generator finished"
Rails.logger.info(finish_text)
end
end
class LocaleGenerator
class << self
def generate(dir_path_to_generate = "config/locales")
spreadsheets_values.each do |sheet_values|
locale_path = Rails.root.join(dir_path_to_generate, "views", sheet_values[:controller], sheet_values[:action])
FileUtils.mkdir_p(locale_path)
locale_to_generate.each do |locale|
# テンプレート内で定義している変数に展開する値
yml_value_hash = {
controller: sheet_values[:controller],
action: sheet_values[:action],
values: sheet_values[locale.to_sym],
}
generate_yml(locale, locale_path, yml_value_hash)
end
end
end
private
def spreadsheets_values
google_spreadsheet_service = GoogleSpreadsheet.instance
google_spreadsheet_service.sheets_values
end
def locale_to_generate
%w[ja en]
end
def generate_yml(locale, locale_path, yml_value_hash)
yml = yml_template(locale, yml_value_hash)
File.open("#{locale_path}/#{locale}.yml", "w") do |file|
file.puts(yml)
end
end
def yml_template(locale, yml_value_hash)
template_head = <<YAML
#{locale}:
#{yml_value_hash[:controller]}:
#{yml_value_hash[:action]}:
YAML
template_key_value_loops = ""
yml_value_hash[:values].each do |k, v|
# 改行が含まれているときは | でつなぐ
# ref: https://qiita.com/tomomomo1217/items/858f290a0dc1a817985c#%E6%94%B9%E8%A1%8C%E3%81%A4%E3%81%8D%E3%81%AE%E6%96%87
if v.include?("\n")
template_key_value =
<<YAML
#{k}: |
YAML
v.split("\n").each do |split_v|
template_value = <<YAML
#{split_v}
YAML
template_key_value += template_value
end
else
template_key_value =
<<YAML
#{k}: "#{v}"
YAML
end
template_key_value_loops += template_key_value
end
template_head + template_key_value_loops
end
end
end
require "rails_helper"
RSpec.describe LocaleGenerator, type: :model do
describe ".generate" do
let(:dir_path_to_generate_for_test) { "spec/dummy_files/locales" }
let(:dir_path) { Rails.root.join(dir_path_to_generate_for_test, "views", "test_controller", "test_action") }
context "スプレッドシート内の文言に改行が含まれていない場合" do
before do
allow(LocaleGenerator).to receive(:spreadsheets_values).and_return([
{
controller: "test_controller",
action: "test_action",
ja: [["test1", "test1_ja"], ["test2", "test2_ja"]],
en: [["test1", "test1_en"], ["test2", "test2_en"]],
},
])
LocaleGenerator.generate(dir_path_to_generate_for_test)
end
# ymlファイル内のテキストをhash形式で取り出す
let(:ja_file_text) { File.open("#{dir_path}/ja.yml") { |file| YAML.load(file) } }
let(:en_file_text) { File.open("#{dir_path}/en.yml") { |file| YAML.load(file) } }
it "spec/dummy_files/locales/:controller/:action/(ja|en).yml がYAML形式で正常に生成されていること" do
expect(File.read("#{dir_path}/ja.yml")).to eq <<YAML
ja:
test_controller:
test_action:
test1: "test1_ja"
test2: "test2_ja"
YAML
expect(File.read("#{dir_path}/en.yml")).to eq <<YAML
en:
test_controller:
test_action:
test1: "test1_en"
test2: "test2_en"
YAML
end
context "ja" do
it "生成されたymlファイル内のキーと文言が正しいこと" do
expect(ja_file_text.has_key?("ja")).to eq true
expect(ja_file_text["ja"].has_key?("test_controller")).to eq true
expect(ja_file_text["ja"]["test_controller"].has_key?("test_action")).to eq true
expect(ja_file_text["ja"]["test_controller"]["test_action"]["test1"]).to eq "test1_ja"
end
end
context "en" do
it "生成されたymlファイル内の文言が正しいこと" do
expect(en_file_text.has_key?("en")).to eq true
expect(en_file_text["en"].has_key?("test_controller")).to eq true
expect(en_file_text["en"]["test_controller"].has_key?("test_action")).to eq true
expect(en_file_text["en"]["test_controller"]["test_action"]["test1"]).to eq "test1_en"
end
end
end
context "スプレッドシート内の文言に改行が含まれている場合" do
before do
allow(LocaleGenerator).to receive(:spreadsheets_values).and_return([
{
controller: "test_controller",
action: "test_action",
ja: [["test1", "test1_ja\ntest1_ja"], ["test2", "test2_ja\ntest2_ja"]],
en: [["test1", "test1_en\ntest1_en"], ["test2", "test2_en\ntest2_en"]],
},
])
LocaleGenerator.generate(dir_path_to_generate_for_test)
end
it "spec/dummy_files/locales/:controller/:action/(ja|en).yml がYAML形式で正常に生成されていること" do
expect(File.read("#{dir_path}/ja.yml")).to eq <<YAML
ja:
test_controller:
test_action:
test1: |
test1_ja
test1_ja
test2: |
test2_ja
test2_ja
YAML
expect(File.read("#{dir_path}/en.yml")).to eq <<YAML
en:
test_controller:
test_action:
test1: |
test1_en
test1_en
test2: |
test2_en
test2_en
YAML
end
end
after do
FileUtils.rm_r(dir_path_to_generate_for_test)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment