From 78049a820c1bf17b1630834f00c8d8ba9952fd96 Mon Sep 17 00:00:00 2001 From: Riccardo Graziosi <31478034+riggraz@users.noreply.github.com> Date: Sun, 5 Jun 2022 11:40:43 +0200 Subject: [PATCH] Add internationalization (#114) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🇬🇧 and 🇮🇹 --- Gemfile | 1 + Gemfile.lock | 3 + app/controllers/admin/users_controller.rb | 4 +- app/controllers/boards_controller.rb | 8 +- app/controllers/comments_controller.rb | 6 +- app/controllers/follows_controller.rb | 4 +- app/controllers/likes_controller.rb | 4 +- app/controllers/post_statuses_controller.rb | 8 +- app/controllers/posts_controller.rb | 6 +- app/helpers/application_helper.rb | 4 +- app/javascript/components/Board/NewPost.tsx | 16 +- .../components/Board/NewPostForm.tsx | 7 +- app/javascript/components/Board/PostList.tsx | 4 +- .../components/Board/PostStatusFilter.tsx | 3 +- .../components/Board/SearchFilter.tsx | 3 +- .../components/Comments/Comment.tsx | 25 ++- .../components/Comments/CommentsP.tsx | 6 +- .../components/Comments/NewComment.tsx | 10 +- .../Comments/NewCommentUpdateSection.tsx | 6 +- app/javascript/components/Post/ActionBox.tsx | 11 +- app/javascript/components/Post/LikeList.tsx | 7 +- app/javascript/components/Post/PostP.tsx | 7 +- .../components/Post/PostStatusSelect.tsx | 3 +- .../components/Post/PostUpdateList.tsx | 14 +- .../SiteSettings/Boards/BoardEditable.tsx | 7 +- .../SiteSettings/Boards/BoardForm.tsx | 12 +- .../Boards/BoardsSiteSettingsP.tsx | 7 +- .../PostStatuses/PostStatusEditable.tsx | 7 +- .../PostStatuses/PostStatusForm.tsx | 10 +- .../PostStatusesSiteSettingsP.tsx | 7 +- .../components/shared/CommentsNumber.tsx | 5 +- .../components/shared/PostStatusLabel.tsx | 3 +- .../components/shared/SiteSettingsInfoBox.tsx | 7 +- app/javascript/components/shared/Spinner.tsx | 3 +- app/javascript/helpers/datetime.ts | 10 +- app/javascript/packs/application.js | 2 + app/javascript/packs/hello_erb.js.erb | 3 + app/javascript/translations/index.js.erb | 4 + app/mailers/user_mailer.rb | 10 +- app/views/devise/confirmations/new.html.erb | 12 +- app/views/devise/passwords/edit.html.erb | 25 ++- app/views/devise/passwords/new.html.erb | 11 +- app/views/devise/registrations/edit.html.erb | 43 +++-- app/views/devise/registrations/new.html.erb | 26 ++- app/views/devise/sessions/new.html.erb | 18 +- app/views/devise/shared/_links.html.erb | 10 +- app/views/devise/unlocks/new.html.erb | 13 +- app/views/layouts/_header.html.erb | 10 +- app/views/layouts/_set_js_locale.html.erb | 6 + app/views/layouts/application.html.erb | 2 + app/views/layouts/mailer.html.erb | 6 +- app/views/layouts/user_mailer.html.erb | 17 ++ app/views/layouts/user_mailer.text.erb | 1 + app/views/site_settings/_menu.html.erb | 6 +- app/views/static_pages/roadmap.html.erb | 2 +- .../user_mailer/notify_comment_owner.html.erb | 35 ++-- ...notify_followers_of_post_status_change.erb | 34 ++-- .../notify_followers_of_post_update.erb | 35 ++-- .../user_mailer/notify_post_owner.html.erb | 35 ++-- config/initializers/locale.rb | 5 + .../locales/activerecord/activerecord.it.yml | 43 +++++ config/locales/{ => devise}/devise.en.yml | 0 config/locales/devise/devise.it.yml | 66 ++++++++ config/locales/en.yml | 157 ++++++++++++++++-- config/locales/it.yml | 148 +++++++++++++++++ config/webpack/environment.js | 2 + config/webpack/loaders/erb.js | 11 ++ config/webpacker.yml | 1 + package.json | 2 + spec/mailers/user_mailer_spec.rb | 1 - yarn.lock | 18 ++ 71 files changed, 802 insertions(+), 266 deletions(-) create mode 100644 app/javascript/packs/hello_erb.js.erb create mode 100644 app/javascript/translations/index.js.erb create mode 100644 app/views/layouts/_set_js_locale.html.erb create mode 100644 app/views/layouts/user_mailer.html.erb create mode 100644 app/views/layouts/user_mailer.text.erb create mode 100644 config/initializers/locale.rb create mode 100644 config/locales/activerecord/activerecord.it.yml rename config/locales/{ => devise}/devise.en.yml (100%) create mode 100644 config/locales/devise/devise.it.yml create mode 100644 config/locales/it.yml create mode 100644 config/webpack/loaders/erb.js diff --git a/Gemfile b/Gemfile index ab1855d9..6d764bfb 100644 --- a/Gemfile +++ b/Gemfile @@ -4,6 +4,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" } ruby '2.6.6' gem 'rails', '6.0.4.7' +gem 'i18n-js' gem 'pg', '>= 0.18', '< 2.0' diff --git a/Gemfile.lock b/Gemfile.lock index dc8404ce..c68ff19a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -112,6 +112,8 @@ GEM activesupport (>= 5.0) i18n (1.10.0) concurrent-ruby (~> 1.0) + i18n-js (3.9.2) + i18n (>= 0.6.6) jbuilder (2.11.5) actionview (>= 5.0.0) activesupport (>= 5.0.0) @@ -297,6 +299,7 @@ DEPENDENCIES capybara (>= 2.15) devise (= 4.7.3) factory_bot_rails (~> 5.0.2) + i18n-js jbuilder (~> 2.7) kaminari (~> 1.2.1) listen (>= 3.0.5, < 3.2) diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 18ab215b..d6cdd8b8 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -11,13 +11,13 @@ module Admin def authenticate_admin unless user_signed_in? - flash[:alert] = 'You must be logged in to access this page.' + flash[:alert] = t('backend.errors.not_logged_in') redirect_to new_user_session_path return end unless current_user.admin? - flash[:alert] = 'You do not have the privilegies to access this page.' + flash[:alert] = t('backend.errors.not_enough_privileges') redirect_to root_path return end diff --git a/app/controllers/boards_controller.rb b/app/controllers/boards_controller.rb index 3f441d66..aa558458 100644 --- a/app/controllers/boards_controller.rb +++ b/app/controllers/boards_controller.rb @@ -20,7 +20,7 @@ class BoardsController < ApplicationController render json: board, status: :created else render json: { - error: I18n.t('errors.board.create', message: board.errors.full_messages) + error: board.errors.full_messages }, status: :unprocessable_entity end end @@ -35,7 +35,7 @@ class BoardsController < ApplicationController print board.errors.full_messages render json: { - error: I18n.t('errors.board.update', message: board.errors.full_messages) + error: board.errors.full_messages }, status: :unprocessable_entity end end @@ -49,7 +49,7 @@ class BoardsController < ApplicationController }, status: :accepted else render json: { - error: I18n.t('errors.board.destroy', message: board.errors.full_messages) + error: board.errors.full_messages }, status: :unprocessable_entity end end @@ -67,7 +67,7 @@ class BoardsController < ApplicationController render json: workflow_output else render json: { - error: I18n.t("errors.board.update_order") + error: t("backend.errors.board.update_order") }, status: :unprocessable_entity end end diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index c5583583..08288634 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -30,7 +30,7 @@ class CommentsController < ApplicationController ), status: :created else render json: { - error: I18n.t('errors.comment.create', message: comment.errors.full_messages) + error: comment.errors.full_messages }, status: :unprocessable_entity end end @@ -41,7 +41,7 @@ class CommentsController < ApplicationController comment.assign_attributes(comment_params) if !current_user.power_user? && current_user.id != post.user_id - render json: I18n.t('errors.unauthorized'), status: :unauthorized + render json: t('backend.errors.unauthorized'), status: :unauthorized return end @@ -51,7 +51,7 @@ class CommentsController < ApplicationController ) else render json: { - error: I18n.t('errors.comment.update', message: comment.errors.full_messages) + error: comment.errors.full_messages }, status: :unprocessable_entity end end diff --git a/app/controllers/follows_controller.rb b/app/controllers/follows_controller.rb index a49e8c49..0036f965 100644 --- a/app/controllers/follows_controller.rb +++ b/app/controllers/follows_controller.rb @@ -20,7 +20,7 @@ class FollowsController < ApplicationController }, status: :created else render json: { - error: I18n.t('errors.follows.create', message: follow.errors.full_messages) + error: follow.errors.full_messages }, status: :unprocessable_entity end end @@ -37,7 +37,7 @@ class FollowsController < ApplicationController }, status: :accepted else render json: { - error: I18n.t('errors.follow.destroy', message: follow.errors.full_messages) + error: follow.errors.full_messages }, status: :unprocessable_entity end end diff --git a/app/controllers/likes_controller.rb b/app/controllers/likes_controller.rb index 261cdcfb..091e9188 100644 --- a/app/controllers/likes_controller.rb +++ b/app/controllers/likes_controller.rb @@ -25,7 +25,7 @@ class LikesController < ApplicationController }, status: :created else render json: { - error: I18n.t('errors.likes.create', message: like.errors.full_messages) + error: like.errors.full_messages }, status: :unprocessable_entity end end @@ -42,7 +42,7 @@ class LikesController < ApplicationController }, status: :accepted else render json: { - error: I18n.t('errors.likes.destroy', message: like.errors.full_messages) + error: like.errors.full_messages }, status: :unprocessable_entity end end diff --git a/app/controllers/post_statuses_controller.rb b/app/controllers/post_statuses_controller.rb index b383b6a3..046d4952 100644 --- a/app/controllers/post_statuses_controller.rb +++ b/app/controllers/post_statuses_controller.rb @@ -16,7 +16,7 @@ class PostStatusesController < ApplicationController render json: post_status, status: :created else render json: { - error: I18n.t('errors.post_status.create', message: post_status.errors.full_messages) + error: post_status.errors.full_messages }, status: :unprocessable_entity end end @@ -29,7 +29,7 @@ class PostStatusesController < ApplicationController render json: post_status, status: :ok else render json: { - error: I18n.t('errors.post_status.update', message: post_status.errors.full_messages) + error: post_status.errors.full_messages }, status: :unprocessable_entity end end @@ -43,7 +43,7 @@ class PostStatusesController < ApplicationController }, status: :accepted else render json: { - error: I18n.t('errors.post_statuses.destroy', message: post_status.errors.full_messages) + error: post_status.errors.full_messages }, status: :unprocessable_entity end end @@ -61,7 +61,7 @@ class PostStatusesController < ApplicationController render json: workflow_output else render json: { - error: I18n.t("errors.post_status.update_order") + error: t("backend.errors.post_status.update_order") }, status: :unprocessable_entity end end diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 9d153f9b..a525541a 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -33,7 +33,7 @@ class PostsController < ApplicationController render json: post, status: :created else render json: { - error: I18n.t('errors.post.create', message: post.errors.full_messages) + error: post.errors.full_messages }, status: :unprocessable_entity end end @@ -54,7 +54,7 @@ class PostsController < ApplicationController post = Post.find(params[:id]) if !current_user.power_user? && current_user.id != post.user_id - render json: I18n.t('errors.unauthorized'), status: :unauthorized + render json: t('backend.errors.unauthorized'), status: :unauthorized return end @@ -83,7 +83,7 @@ class PostsController < ApplicationController render json: post, status: :no_content else render json: { - error: I18n.t('errors.post.update', message: post.errors.full_messages) + error: post.errors.full_messages }, status: :unprocessable_entity end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index cac248d0..af9cfc89 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,13 +1,13 @@ module ApplicationHelper def authenticate_admin unless user_signed_in? - flash[:alert] = 'You must be logged in to access this page.' + flash[:alert] = t('backend.errors.not_logged_in') redirect_to new_user_session_path return end unless current_user.moderator? || current_user.admin? - flash[:alert] = 'You do not have the privilegies to access this page.' + flash[:alert] = t('backend.errors.not_enough_privileges') redirect_to root_path return end diff --git a/app/javascript/components/Board/NewPost.tsx b/app/javascript/components/Board/NewPost.tsx index 4b8ccc87..4d43766b 100644 --- a/app/javascript/components/Board/NewPost.tsx +++ b/app/javascript/components/Board/NewPost.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import I18n from 'i18n-js'; import NewPostForm from './NewPostForm'; import Spinner from '../shared/Spinner'; @@ -86,7 +87,7 @@ class NewPost extends React.Component { if (title === '') { this.setState({ - error: 'You forgot to enter a title!', + error: I18n.t('board.new_post.no_title'), isLoading: false, }); return; @@ -109,7 +110,7 @@ class NewPost extends React.Component { if (res.status === HttpStatus.Created) { this.setState({ - success: 'Post published! You will be redirected soon...', + success: I18n.t('board.new_post.submit_success'), title: '', description: '', @@ -124,7 +125,7 @@ class NewPost extends React.Component { } catch (e) { this.setState({ - error: 'An unknown error occurred, try again.' + error: I18n.t('board.new_post.submit_error') }); } } @@ -151,11 +152,16 @@ class NewPost extends React.Component { onClick={this.toggleForm} className="submitBtn" outline={showForm}> - { showForm ? 'Cancel' : 'Submit feedback' } + { + showForm ? + I18n.t('board.new_post.cancel_button') + : + I18n.t('board.new_post.submit_button') + } : - Log in / Sign up + {I18n.t('board.new_post.login_button')} } diff --git a/app/javascript/components/Board/NewPostForm.tsx b/app/javascript/components/Board/NewPostForm.tsx index 608a64a2..1769ec65 100644 --- a/app/javascript/components/Board/NewPostForm.tsx +++ b/app/javascript/components/Board/NewPostForm.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import I18n from 'i18n-js'; import Button from '../shared/Button'; @@ -20,7 +21,7 @@ const NewPostForm = ({
- +
- +
diff --git a/app/javascript/components/Board/PostList.tsx b/app/javascript/components/Board/PostList.tsx index 01be7d12..26d20bd2 100644 --- a/app/javascript/components/Board/PostList.tsx +++ b/app/javascript/components/Board/PostList.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; - +import I18n from 'i18n-js'; import InfiniteScroll from 'react-infinite-scroller'; import PostListItem from './PostListItem'; @@ -64,7 +64,7 @@ const PostList = ({ /> )) : - areLoading ?

: There are no posts. + areLoading ?

: {I18n.t('board.posts_list.empty')} } diff --git a/app/javascript/components/Board/PostStatusFilter.tsx b/app/javascript/components/Board/PostStatusFilter.tsx index 3830a41e..78f919e2 100644 --- a/app/javascript/components/Board/PostStatusFilter.tsx +++ b/app/javascript/components/Board/PostStatusFilter.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import I18n from 'i18n-js'; import PostStatusListItem from './PostStatusListItem'; import Spinner from '../shared/Spinner'; @@ -24,7 +25,7 @@ const PostStatusFilter = ({ currentFilter, }: Props) => (
- Filter by status + {I18n.t('board.filter_box.title')} { postStatuses.map((postStatus, i) => ( (
- Search + {I18n.t('board.search_box.title')} {userFullName} - { isPostUpdate ? Post update : null } + { + isPostUpdate ? + + {I18n.t('post.comments.post_update_badge')} + + : + null + }

{body}

- { replyForm.isOpen ? 'Cancel' : 'Reply' } + { + replyForm.isOpen ? + I18n.t('common.buttons.cancel') + : + I18n.t('post.comments.reply_button') + } { isPowerUser ? @@ -68,14 +81,18 @@ const Comment = ({ { 'Post update: ' + (isPostUpdate ? 'yes' : 'no') } - Edit + + {I18n.t('common.buttons.edit')} + Delete + data-turbolinks="false"> + {I18n.t('common.buttons.delete')} + : diff --git a/app/javascript/components/Comments/CommentsP.tsx b/app/javascript/components/Comments/CommentsP.tsx index 1a25c011..e42f3966 100644 --- a/app/javascript/components/Comments/CommentsP.tsx +++ b/app/javascript/components/Comments/CommentsP.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import I18n from 'i18n-js'; import NewComment from './NewComment'; import CommentList from './CommentList'; @@ -7,6 +8,7 @@ import { DangerText } from '../shared/CustomTexts'; import IComment from '../../interfaces/IComment'; import { ReplyFormState } from '../../reducers/replyFormReducer'; +import Separator from '../shared/Separator'; interface Props { postId: number; @@ -106,7 +108,9 @@ class CommentsP extends React.Component { { error ? {error} : null }
- activity • {comments.length} comment{comments.length === 1 ? '' : 's'} + {I18n.t('post.comments.title')} + + {I18n.t('common.comments_number', { count: comments.length })}
{ @@ -70,9 +71,12 @@ const NewComment = ({ } : - You need to log in to post comments. + + {I18n.t('post.new_comment.not_logged_in')} + }
+ { error ? {error} : null } ); diff --git a/app/javascript/components/Comments/NewCommentUpdateSection.tsx b/app/javascript/components/Comments/NewCommentUpdateSection.tsx index 1818dc17..4ecb7b6d 100644 --- a/app/javascript/components/Comments/NewCommentUpdateSection.tsx +++ b/app/javascript/components/Comments/NewCommentUpdateSection.tsx @@ -1,4 +1,6 @@ import * as React from 'react'; +import I18n from 'i18n-js'; + import { MutedText } from '../shared/CustomTexts'; interface Props { @@ -19,11 +21,11 @@ const NewCommentUpdateSection = ({ checked={postUpdateFlagValue || false} />   - + { postUpdateFlagValue ? - Users that follow this post will be notified + {I18n.t('post.new_comment.user_notification')} : null } diff --git a/app/javascript/components/Post/ActionBox.tsx b/app/javascript/components/Post/ActionBox.tsx index 07c649f7..afb985a5 100644 --- a/app/javascript/components/Post/ActionBox.tsx +++ b/app/javascript/components/Post/ActionBox.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; -import Button from '../shared/Button'; +import I18n from 'i18n-js'; +import Button from '../shared/Button'; import { BoxTitleText, SmallMutedText } from '../shared/CustomTexts'; interface Props { @@ -13,17 +14,17 @@ interface Props { const ActionBox = ({followed, submitFollow, isLoggedIn}: Props) => (
- Actions + {I18n.t('post.action_box.title')}

{ followed ? - 'you\'re receiving notifications about new updates on this post' + I18n.t('post.action_box.following_description') : - 'you won\'t receive notifications about this post' + I18n.t('post.action_box.not_following_description') }
diff --git a/app/javascript/components/Post/LikeList.tsx b/app/javascript/components/Post/LikeList.tsx index 7b315dca..533fd761 100644 --- a/app/javascript/components/Post/LikeList.tsx +++ b/app/javascript/components/Post/LikeList.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import I18n from 'i18n-js'; import Gravatar from 'react-gravatar'; import ILike from '../../interfaces/ILike'; @@ -17,11 +18,13 @@ interface Props { const LikeList = ({ likes, areLoading, error}: Props) => (
- Likes + {I18n.t('post.likes_box.title')} + { areLoading ? : null } { error ? {error} : null } +
- { likes.length === 0 ? There are no likes yet. : null } + { likes.length === 0 ? {I18n.t('post.likes_box.empty')} : null } { likes.map((like, i) => (
diff --git a/app/javascript/components/Post/PostP.tsx b/app/javascript/components/Post/PostP.tsx index 7efc5131..f14632ff 100644 --- a/app/javascript/components/Post/PostP.tsx +++ b/app/javascript/components/Post/PostP.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import I18n from 'i18n-js'; import IPost from '../../interfaces/IPost'; import IPostStatus from '../../interfaces/IPostStatus'; @@ -135,7 +136,11 @@ class PostP extends React.Component {

{post.title}

{ isPowerUser && post ? - Edit : null + + {I18n.t('post.edit_button')} + + : + null }
{ diff --git a/app/javascript/components/Post/PostStatusSelect.tsx b/app/javascript/components/Post/PostStatusSelect.tsx index d01daa0a..bf2d3323 100644 --- a/app/javascript/components/Post/PostStatusSelect.tsx +++ b/app/javascript/components/Post/PostStatusSelect.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import I18n from 'i18n-js'; import IPostStatus from '../../interfaces/IPostStatus'; @@ -35,7 +36,7 @@ const PostStatusSelect = ({ ))} - + ); diff --git a/app/javascript/components/Post/PostUpdateList.tsx b/app/javascript/components/Post/PostUpdateList.tsx index 7a30518c..c7409738 100644 --- a/app/javascript/components/Post/PostUpdateList.tsx +++ b/app/javascript/components/Post/PostUpdateList.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import I18n from 'i18n-js'; import Gravatar from 'react-gravatar'; import { BoxTitleText, DangerText, CenteredMutedText, MutedText } from '../shared/CustomTexts'; @@ -25,11 +26,18 @@ const PostUpdateList = ({ error, }: Props) => (
- Updates + {I18n.t('post.updates_box.title')} + { areLoading ? : null } { error ? {error} : null } +
- { postUpdates.length === 0 ? There are no updates yet. : null } + { + postUpdates.length === 0 ? + {I18n.t('post.updates_box.empty')} + : + null + } { postUpdates.map((postUpdate, i) => (
@@ -43,7 +51,7 @@ const PostUpdateList = ({ postUpdate.body : - changed status to  + {I18n.t('post.updates_box.status_change')}  postStatus.id === postUpdate.postStatusId)} /> diff --git a/app/javascript/components/SiteSettings/Boards/BoardEditable.tsx b/app/javascript/components/SiteSettings/Boards/BoardEditable.tsx index d8f90af2..15b8c3dd 100644 --- a/app/javascript/components/SiteSettings/Boards/BoardEditable.tsx +++ b/app/javascript/components/SiteSettings/Boards/BoardEditable.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import I18n from 'i18n-js'; import { Draggable } from 'react-beautiful-dnd'; import { DescriptionText } from '../../shared/CustomTexts'; @@ -82,7 +83,7 @@ class BoardsEditable extends React.Component {
- Edit + {I18n.t('common.buttons.edit')} @@ -90,7 +91,7 @@ class BoardsEditable extends React.Component { onClick={() => handleDelete(id)} data-confirm="Are you sure?" > - Delete + {I18n.t('common.buttons.delete')}
@@ -107,7 +108,7 @@ class BoardsEditable extends React.Component { - Cancel + {I18n.t('common.buttons.cancel')} } diff --git a/app/javascript/components/SiteSettings/Boards/BoardForm.tsx b/app/javascript/components/SiteSettings/Boards/BoardForm.tsx index 8fcba403..13b04bad 100644 --- a/app/javascript/components/SiteSettings/Boards/BoardForm.tsx +++ b/app/javascript/components/SiteSettings/Boards/BoardForm.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import I18n from 'i18n-js'; import Button from '../../shared/Button'; @@ -83,7 +84,7 @@ class BoardForm extends React.Component {
this.onNameChange(e.target.value)} className="form-control" @@ -94,12 +95,17 @@ class BoardForm extends React.Component { className="newBoardButton" disabled={!this.isFormValid()} > - {mode === 'create' ? 'Create' : 'Save'} + { + mode === 'create' ? + I18n.t('common.buttons.create') + : + I18n.t('common.buttons.update') + }