Lucky - i18n
Add Internationalization support to a Lucky Application
Used 172 times
S
Stephen Dolan
Template Source
Review the code before running this template on your machine.
def generate_user_language_database_migration(initial_language_code)
say "Generating migration to add language to users", :yellow
migration_output = run "lucky gen.migration AddLanguageToUser", capture: true
migration_file = migration_output[/db\/migrations\/\S*_add_language_to_user\.cr/]
say "Removing default content from generated migration", :yellow
gsub_file migration_file, /^\s+#.*\n/, ""
say "Modifying generated migration logic", :yellow
insert_into_file migration_file, after: "def migrate\n" do
<<-EOF
alter table_for(User) do
add language : String, default: "#{initial_language_code}"
end
EOF
end
say "Modifying generated migration rollback", :yellow
insert_into_file migration_file, after: "def rollback\n" do
<<-EOF
alter table_for(User) do
remove :language
end
EOF
end
if yes? "Do you want to run the new migration now? [y/N]", :green
say "Running migration", :yellow
run "lucky db.setup"
run "lucky db.migrate"
end
end
say "Adding i18n Shard to shard.yml", :yellow
insert_into_file "shard.yml", after: "dependencies:\n" do
<<-EOF
i18n:
github: TechMagister/i18n.cr
EOF
end
say "Requiring i18n shard in src/shards.cr", :yellow
append_to_file "src/shards.cr" do
<<~EOF
require "i18n"
EOF
end
say "Installing shards", :yellow
run "shards install"
say "Creating config/locales for translations", :yellow
create_file "config/locales/.keep"
initial_language_code = ask "Which country code would you like the default config file generated for?", :green, default: "en"
hello_translation = ask "How do you say 'Hello' in that country?", :green, default: "Hello"
create_file "config/locales/#{initial_language_code}.yml" do
<<~EOF
# t("simple_example.hello")
# => "Hello"
simple_example:
hello: "#{hello_translation}"
# t("interpolation_example.hello", { username: "LuckyCasts" })
# => "Hello, LuckyCasts"
interpolation_example:
hello: "#{hello_translation}, %{username}"
# t("count_example.apple", count: 2)
# => "2 apples"
count_example:
apple:
one: "%{count} apple"
other: "%{count} apples"
EOF
end
say "Creating i18n.cr to load translations", :yellow
create_file "config/i18n.cr" do
<<~EOF
I18n.load_path += ["config/locales/**/"]
I18n.init
I18n.default_locale = "#{initial_language_code}"
EOF
end
if Dir.glob("db/migrations/*add_language_to_user.cr").empty?
generate_user_language_database_migration(initial_language_code)
else
say "Migration already exists. Skipping generation", :yellow
end
say "Adding language column to User model file"
insert_into_file "src/models/user.cr", after: "table do\n" do
<<-EOF
column language : String
EOF
end
say "Creating src/translator.cr module for translation logic", :yellow
create_file "src/translator.cr" do
<<~EOF
module Translator
LANGUAGE_DEFAULT = I18n.default_locale
LANGUAGES_AVAILABLE = [LANGUAGE_DEFAULT]
# Modify as necessary for other languages. For example:
# LANGUAGE_DEFAULT = I18n.default_locale
# LANGUAGES_AVAILABLE = [I18n.default_locale, "es"]
# For more information on options you can pass to I18n.translate:
# See https://github.com/TechMagister/i18n.cr
def t(*args, **nargs)
I18n.locale = user_language
I18n.translate(*args, **nargs)
end
# In places where current_user / user isn't available, be sure to override this method:
# quick_def user_language, LANGUAGE_DEFAULT
def user_language
current_user.try(&.language) || LANGUAGE_DEFAULT
end
end
EOF
end
say "Requiring new translator module in src/app.cr", :yellow
insert_into_file "src/app.cr", after: "Lucky::AssetHelpers.load_manifest\n\n" do
<<~EOF
require "./translator"
EOF
end
if File.exists?("src/operations/sign_up_user.cr")
say "Requiring language for new user sign up", :yellow
gsub_file "src/operations/sign_up_user.cr", /permit_columns (.*)$/, "permit_columns language, \\1"
insert_into_file "src/operations/sign_up_user.cr", after: "before_save do\n" do
<<-EOF
language.value ||= Translator::LANGUAGE_DEFAULT
validate_inclusion_of language, in: Translator::LANGUAGES_AVAILABLE
EOF
end
end
if File.exists?("src/pages/main_layout.cr")
say "Including Translator module in MainLayout for use in front end", :yellow
insert_into_file "src/pages/main_layout.cr", after: "include Lucky::HTMLPage\n" do
<<-EOF
include Translator
EOF
end
end
if File.exists?("src/pages/auth_layout.cr")
say "Including Translator module in AuthLayout for use in front end", :yellow
insert_into_file "src/pages/auth_layout.cr", after: "include Lucky::HTMLPage\n" do
<<-EOF
include Translator
quick_def user_language, LANGUAGE_DEFAULT
EOF
end
end
if File.exists?("src/pages/errors/show_page.cr")
say "Including Translator module in Errors::ShowPage for use in front end", :yellow
insert_into_file "src/pages/errors/show_page.cr", after: "include Lucky::HTMLPage\n" do
<<-EOF
include Translator
quick_def user_language, LANGUAGE_DEFAULT
EOF
end
end
if File.exists?("src/actions/browser_action.cr")
say "Including Translator module in BrowserAction for use in browser actions", :yellow
insert_into_file "src/actions/browser_action.cr", after: "abstract class BrowserAction < Lucky::Action\n" do
<<-EOF
include Translator\n
EOF
end
end
if File.exists?("src/actions/api_action.cr")
say "Including Translator module in ApiAction for use in API actions", :yellow
insert_into_file "src/actions/api_action.cr", after: "abstract class ApiAction < Lucky::Action\n" do
<<-EOF
include Translator\n
EOF
end
end
say "Done! For examples of how to use translations in pages themselves, visit the Lucky Guides here: https://luckyframework.org/guides/frontend/internationalization", :green