Skip to content

Commit

Permalink
feat: add localization and setup changing languages
Browse files Browse the repository at this point in the history
  • Loading branch information
kkkiikkk committed Aug 22, 2024
1 parent 69e5e0d commit 6d738ef
Show file tree
Hide file tree
Showing 12 changed files with 183 additions and 62 deletions.
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ gem 'rspec-rails'
gem 'factory_bot_rails', '~> 6.4', '>= 6.4.3'

gem 'faker'

gem 'i18n'
# Use Redis adapter to run Action Cable in production
# gem "redis", ">= 4.0.1"

Expand Down
10 changes: 10 additions & 0 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
# frozen_string_literal: true

class ApplicationController < ActionController::Base
before_action :set_locale

def set_locale
I18n.locale = params[:locale] || I18n.default_locale
end

def default_url_options
{ locale: I18n.locale }
end

def index
@images = Image.take(5)
end
Expand Down
6 changes: 1 addition & 5 deletions app/javascript/application.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import "bootstrap"
import "@hotwired/turbo-rails"
window.process = { env: { NODE_ENV: 'production' } };
import '@popperjs/core'
import "popper"
import "bootstrap"
import "controllers"
import "./upload.js"
import "./modal.js"
// import "./rails_admin.js"
// import 'rails_admin/dist/rails_admin.js';

6 changes: 4 additions & 2 deletions app/views/application/index.html.slim
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
div
.container-welcome
h1.title WELCOME SMOG
p.text Smog is a new platform to store and share images with everyone. You can comment or like some pictures, but for that you have to sign up.
h1.title
= t('home.welcome_title')
p.text
= t('home.welcome_description')

div.carousel-container

Expand Down
6 changes: 3 additions & 3 deletions app/views/categories/index.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ div.category-container
= category[:name]
- if user_signed_in?
- if category.subscriptions.empty?
= button_to "Subscribe", category_subscriptions_path(category), data: { turbo_method: :post }, method: :post, class: "category-btn"
= button_to t('categories.subscribe_button'), category_subscriptions_path(category), data: { turbo_method: :post }, method: :post, class: "category-btn"
- else
= button_to "Unsubscribe", category_subscription_path(category, category.subscriptions[0]), data: { turbo_method: :delete }, method: :delete, class: "category-btn"
= button_to t('categories.unsubscribe_button'), category_subscription_path(category, category.subscriptions[0]), data: { turbo_method: :delete }, method: :delete, class: "category-btn"
- else
= button_to "Subscribe", new_user_session_path, data: { turbo: false }, method: :get, class: "category-btn"
= button_to t('categories.subscribe_button'), new_user_session_path, data: { turbo: false }, method: :get, class: "category-btn"
17 changes: 12 additions & 5 deletions app/views/images/_modal.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,29 @@
= image_tag image.image.url(:thumb), id: "modalImage", class: "fixed-dimensions"
.like-section
p
| Likes: #{image.likes.size}
| #{t('image_info.likes_title')}: #{image.likes.size}
= button_to category_image_likes_path(category.slug, image), method: :post, class: "btn btn-link" do
= image_tag "like.svg", class: "like-image"
.comments-container
h5 Comments
h5
= t('image_info.likes_title')
.comment-form
= form_with model: [category, image, Comment.new], local: true, html: { id: 'commentForm', data: { image_id: image.id } } do |f|
.form-group
= recaptcha_tags
.form-group
= f.label :caption
= f.label t('image_info.caption')
= f.text_area :caption, class: "form-control", rows: 3
.form-group
= f.submit 'Add Comment', class: "btn btn-primary"
= f.submit t('image_info.add_comment'), class: "btn btn-primary"
.comments-list
= render partial: 'comments/comments_list', locals: { comments: image.comments }
.modal-footer
= link_to 'Close', category_path(category.slug), class: "btn btn-secondary"
= link_to t('image_info.close_image'), category_path(category.slug), class: "btn btn-secondary"
.modal-backdrop.fade.show
/ image_info:
/ comments_title: 'Коментарі'
/ caption: 'Опис'
/ add_comment: 'Додати коментар'
/ close_image: 'Закрити'
/ likes_title: 'Сподобалося'
9 changes: 5 additions & 4 deletions app/views/images/new.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
.col-md-6
= form_with model: @image, local: true, html: { multipart: true } do |f|
.form-group
= f.label :category_name, "Category Name"
= f.label :category_name, t('app_pin_page.category_input_label')
= f.text_field :category_name, class: "form-control"
.image-preview.hidden
.form-group.upload-container
input#file-upload type="file" name="image[image]" class="form-control-file"
label for="file-upload"
span.icon
i class="fas fa-arrow-up"
span.text Select a file or drag it here
span.text
= t('app_pin_page.category_recommend_text')
.upload-info
| We recommend using high quality .jpg files (less than 20MB in size)
= t('app_pin_page.image_upload_info')
.form-group
= f.submit 'Upload', class: 'signup-button', disabled: true
= f.submit t('app_pin_page.submit_image'), class: 'signup-button', disabled: true
33 changes: 21 additions & 12 deletions app/views/layouts/application.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,40 @@ html
body
nav.navbar.navbar-expand-lg.bg-body-tertiary
.container-fluid
= link_to "SMOG", root_path, class: "navbar-brand order-0"
button.navbar-toggler.order-1 type="button" data-bs-toggle="collapse" data-bs-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation"
span.navbar-toggler-icon
#navbarText.collapse.navbar-collapse.order-2
ul.navbar-nav.ms-auto.mb-2.mb-lg-0
ul.navbar-nav.me-auto.mb-2.mb-lg-0
li.nav-item
= link_to "Home", root_path, class: "nav-link #{'active' if current_page?(root_path)}", aria: { current: "page" }, data: { turbo: false }
= link_to t('navigator.home'), root_path, class: "nav-link #{'active' if current_page?(root_path)}", aria: { current: "page" }, data: { turbo: false }
li.nav-item
= link_to "Explore", images_path, class: "nav-link #{'active' if current_page?(images_path)}", data: { turbo: false }
= link_to t('navigator.explore'), images_path, class: "nav-link #{'active' if current_page?(images_path)}", data: { turbo: false }
- if user_signed_in?
li.nav-item
= link_to "Add pin", new_image_path, class: "nav-link #{'active' if current_page?(new_image_path)}", data: { turbo: false }
li.nav-item
= link_to "Categories", categories_path, class: "nav-link #{'active' if current_page?(categories_path)}", data: { turbo: false }
li.nav-item
= link_to "Profile", edit_user_registration_path, class: "nav-link #{'active' if current_page?(edit_user_registration_path)}", data: { turbo: false }
= link_to t('navigator.add_pin'), new_image_path, class: "nav-link #{'active' if current_page?(new_image_path)}", data: { turbo: false }
li.nav-item
= link_to t('navigator.category'), categories_path, class: "nav-link #{'active' if current_page?(categories_path)}", data: { turbo: false }
li.nav-item
= link_to t('navigator.profile'), edit_user_registration_path, class: "nav-link #{'active' if current_page?(edit_user_registration_path)}", data: { turbo: false }
li.nav-item.dropdown
a.nav-link.dropdown-toggle href="#" id="languageDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"
= t('language')
ul.dropdown-menu aria-labelledby="languageDropdown"
li
= link_to "English", url_for(locale: 'en'), class: "dropdown-item"
li
= link_to "Українська", url_for(locale: 'ua'), class: "dropdown-item"
ul.navbar-nav.ms-auto
li.nav-item
- if user_signed_in?
= link_to "Log out", destroy_user_session_path, data: { turbo_method: :delete }, class: "btn-signup"
= link_to t('navigator.log_out'), destroy_user_session_path, data: { turbo_method: :delete }, class: "btn-signup"
- else
= link_to "Sign up", new_user_registration_path, class: "btn-signup"
= link_to t('navigator.sign_up'), new_user_registration_path, class: "btn-signup"

div
= yield

footer.footer
.footer-content
| Smog developed by
= t('footer.developed_by')
a href="https://github.com/kkkiikkk" target="_blank" kkkiikkk
4 changes: 4 additions & 0 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ class Application < Rails::Application
config.active_job.queue_adapter = :resque
config.action_dispatch.cookies_same_site_protection = :none
config.action_controller.default_protect_from_forgery = false if ENV['RAILS_ENV'] == 'development'
config.i18n.default_locale = :ua
config.i18n.available_locales = [:en, :ua]
config.i18n.fallbacks = true


# Configuration for the application, engines, and railties goes here.
#
Expand Down
63 changes: 63 additions & 0 deletions config/locales/devise.ua.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
ua:
devise:
confirmations:
confirmed: "Ваша електронна адреса успішно підтверджена."
send_instructions: "Ви отримаєте лист із інструкціями, як підтвердити вашу електронну адресу, через кілька хвилин."
send_paranoid_instructions: "Якщо ваша електронна адреса існує в нашій базі даних, ви отримаєте лист із інструкціями щодо підтвердження вашої електронної адреси через кілька хвилин."
failure:
already_authenticated: "Ви вже увійшли в систему."
inactive: "Ваш акаунт ще не активовано."
invalid: "Невірний %{authentication_keys} або пароль."
locked: "Ваш акаунт заблоковано."
last_attempt: "У вас залишилась одна спроба перед блокуванням акаунту."
not_found_in_database: "Невірний %{authentication_keys} або пароль."
timeout: "Сеанс закінчився. Будь ласка, увійдіть знову, щоб продовжити."
unauthenticated: "Ви повинні увійти або зареєструватися перед продовженням."
unconfirmed: "Ви повинні підтвердити свою електронну адресу перед продовженням."
mailer:
confirmation_instructions:
subject: "Інструкції щодо підтвердження"
reset_password_instructions:
subject: "Інструкції щодо скидання пароля"
unlock_instructions:
subject: "Інструкції щодо розблокування"
email_changed:
subject: "Електронна адреса змінена"
password_change:
subject: "Пароль змінено"
omniauth_callbacks:
failure: "Не вдалося автентифікувати вас через %{kind}, тому що \"%{reason}\"."
success: "Успішно автентифіковано через обліковий запис %{kind}."
passwords:
no_token: "Ви не можете отримати доступ до цієї сторінки без посилання на скидання пароля. Якщо ви прийшли з листа про скидання пароля, переконайтеся, що ви використали повний URL, наданий у листі."
send_instructions: "Ви отримаєте лист із інструкціями щодо скидання пароля через кілька хвилин."
send_paranoid_instructions: "Якщо ваша електронна адреса існує в нашій базі даних, ви отримаєте посилання на відновлення пароля на свою електронну адресу через кілька хвилин."
updated: "Ваш пароль успішно змінено. Ви тепер увійшли в систему."
updated_not_active: "Ваш пароль успішно змінено."
registrations:
destroyed: "До побачення! Ваш акаунт успішно скасовано. Сподіваємося побачити вас знову незабаром."
signed_up: "Ласкаво просимо! Ви успішно зареєструвалися."
signed_up_but_inactive: "Ви успішно зареєструвалися. Однак ми не змогли вас увійти, оскільки ваш акаунт ще не активовано."
signed_up_but_locked: "Ви успішно зареєструвалися. Однак ми не змогли вас увійти, оскільки ваш акаунт заблоковано."
signed_up_but_unconfirmed: "Повідомлення з посиланням на підтвердження було надіслано на вашу електронну адресу. Будь ласка, перейдіть за посиланням, щоб активувати свій акаунт."
update_needs_confirmation: "Ви успішно оновили свій акаунт, але нам потрібно підтвердити вашу нову електронну адресу. Будь ласка, перевірте свою електронну пошту та перейдіть за посиланням для підтвердження нової електронної адреси."
updated: "Ваш акаунт успішно оновлено."
updated_but_not_signed_in: "Ваш акаунт успішно оновлено, але оскільки ваш пароль був змінений, вам потрібно увійти знову."
sessions:
signed_in: "Ви успішно увійшли в систему."
signed_out: "Ви успішно вийшли з системи."
already_signed_out: "Ви успішно вийшли з системи."
unlocks:
send_instructions: "Ви отримаєте лист із інструкціями, як розблокувати ваш акаунт, через кілька хвилин."
send_paranoid_instructions: "Якщо ваш акаунт існує, ви отримаєте лист із інструкціями, як розблокувати його через кілька хвилин."
unlocked: "Ваш акаунт успішно розблоковано. Будь ласка, увійдіть, щоб продовжити."
errors:
messages:
already_confirmed: "вже було підтверджено, будь ласка, спробуйте увійти в систему"
confirmation_period_expired: "потрібно підтвердити протягом %{period}, будь ласка, запросіть новий"
expired: "закінчився, будь ласка, запросіть новий"
not_found: "не знайдено"
not_locked: "не було заблоковано"
not_saved:
one: "1 помилка завадила збереженню цього %{resource}:"
other: "%{count} помилок завадили збереженню цього %{resource}:"
60 changes: 29 additions & 31 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
# Files in the config/locales directory are used for internationalization and
# are automatically loaded by Rails. If you want to use locales other than
# English, add the necessary files in this directory.
#
# To use the locales, use `I18n.t`:
#
# I18n.t "hello"
#
# In views, this is aliased to just `t`:
#
# <%= t("hello") %>
#
# To use a different locale, set it with `I18n.locale`:
#
# I18n.locale = :es
#
# This would use the information in config/locales/es.yml.
#
# To learn more about the API, please read the Rails Internationalization guide
# at https://guides.rubyonrails.org/i18n.html.
#
# Be aware that YAML interprets the following case-insensitive strings as
# booleans: `true`, `false`, `on`, `off`, `yes`, `no`. Therefore, these strings
# must be quoted to be interpreted as strings. For example:
#
# en:
# "yes": yup
# enabled: "ON"

en:
hello: "Hello world"
en:
language: 'Language'
home:
welcome_title: 'Welcome to SMOG'
welcome_description: 'Smog is a new platform for storing and sharing images with everyone. You can comment on or like some photos, but you need to register to do so.'
navigator:
category: 'Categories'
home: 'Home'
explore: 'Explore'
profile: 'My Profile'
add_pin: 'Add Pin'
log_out: 'Log Out'
sign_up: 'Create New Account'
footer:
developed_by: 'Developed by '
app_pin_page:
category_input_label: 'Category Name'
category_recommend_text: 'Select a file or drag it here'
image_upload_info: 'We recommend using high-quality .jpg files (size less than 20MB)'
submit_image: 'Upload'
categories:
subscribe_button: 'Subscribe'
unsubscribe_button: 'Unsubscribe'
image_info:
comments_title: 'Comments'
caption: 'Caption'
add_comment: 'Add Comment'
close_image: 'Close'
likes_title: 'Likes'
29 changes: 29 additions & 0 deletions config/locales/ua.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
ua:
language: 'Мова'
home:
welcome_title: 'Вітаємо у SMOG'
welcome_description: 'Smog – це нова платформа для зберігання та обміну зображеннями з усіма. Ви можете коментувати або лайкати деякі фотографії, але для цього вам потрібно зареєструватися.'
navigator:
category: 'Категорії'
home: 'Головна'
explore: 'Досліджувати'
profile: 'Мій профіль'
add_pin: 'Додати нову картинку'
log_out: 'Вийти'
sign_up: 'Створити новий акаунт'
footer:
developed_by: 'Створено розробником '
app_pin_page:
category_input_label: 'Назва категорії'
category_recommend_text: 'Виберіть файл або перетягніть його'
image_upload_info: 'Ми рекомендуємо використовувати файли високої якості .jpg (розмір менше 20 МБ)'
submit_image: 'Завантажити'
categories:
subscribe_button: 'Підписатись'
unsubscribe_button: 'Відписатись'
image_info:
comments_title: 'Коментарі'
caption: 'Опис'
add_comment: 'Додати коментар'
close_image: 'Закрити'
likes_title: 'Сподобалося'

0 comments on commit 6d738ef

Please sign in to comment.