Skip to content

Instantly share code, notes, and snippets.

@ksss
Created February 5, 2025 05:35
Show Gist options
  • Save ksss/b1988f09940617896a1f9ff3968975a2 to your computer and use it in GitHub Desktop.
Save ksss/b1988f09940617896a1f9ff3968975a2 to your computer and use it in GitHub Desktop.
Generate L10n file to rb and rbs
#! /usr/bin/env ruby
class Generator
def initialize(base_locale:, root_name:, rb_path:, rbs_path:)
@base_locale = base_locale.to_sym
@root_name = root_name
@rb_path = rb_path
@rbs_path = rbs_path
@stack = nil
@mode = nil
@indent = 0
end
def write
I18n.with_locale(@base_locale) do
write_rb { on_root }
write_rbs { on_root }
end
end
def write_rb
@mode = :rb
@io = File.open(@rb_path, 'w')
yield
$stdout.puts "Write rb to #{@rb_path}"
end
def write_rbs
@mode = :rbs
@io = File.open(@rbs_path, 'w')
yield
$stdout.puts "Write rbs to #{@rbs_path}"
end
def on_root
puts "module #{@root_name}"
nest do
@stack = []
on_member(I18n.config.backend.translations[@base_locale])
end
puts 'end'
end
def on_member(hash)
hash.each_with_index do |(key, value), index|
next unless key.match?(/^[a-z]/)
@stack.push(key)
case value
when Hash
puts "# #{@stack.join('.')}"
case @mode
when :rb
puts "def self.#{under_score(key)} = #{camelcase(key)}"
when :rbs
puts "def self.#{under_score(key)}: () -> singleton(#{camelcase(key)})"
end
puts "module #{camelcase(key)}"
nest do
on_member(value)
end
puts 'end'
puts if index != hash.size - 1
when String, Array, Integer, true, false, nil
case @mode
when :rb
puts "def self.#{under_score(key)} = ::I18n.t('#{@stack.join('.')}')"
when :rbs
case value
when String
# preview comment
puts "# #{I18n.t(@stack.join('.')).split("\n", 2).first}"
type = 'String'
when Array
type = 'Array[untyped]'
when Integer
type = 'Integer'
else
type = value.inspect
end
puts "def self.#{under_score(key)}: () -> #{type}"
end
puts if index != hash.size - 1
when Proc
# puts "def #{under_score(key)} = #{value.call.inspect}"
else
# binding.irb
end
@stack.pop
end
end
def nest
@indent += 1
yield
@indent -= 1
end
def puts(str = nil)
if str
@io.puts("#{' ' * @indent}#{str}")
else
@io.puts
end
end
def camelcase(sym)
sym.to_s.camelcase.gsub(%r{[/-]}, '_')
end
def under_score(sym)
sym.to_s.gsub(%r{[/-]}, '_')
end
end
Generator.new(
base_locale: :ja,
root_name: 'L10n',
rb_path: 'app/models/l10n.rb',
rbs_path: 'sig/app/models/l10n.rbs',
).write
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment