From 38803823c2320644f1b1536bd133aa3ddc6955e3 Mon Sep 17 00:00:00 2001 From: Benedikt Laube Date: Tue, 21 Oct 2025 10:15:38 +0200 Subject: [PATCH 01/13] Prepare gem for i18n --- authentication-zero.gemspec | 3 +++ lib/authentication_zero.rb | 3 +++ lib/authentication_zero/locales/en.yml | 2 ++ 3 files changed, 8 insertions(+) create mode 100644 lib/authentication_zero/locales/en.yml diff --git a/authentication-zero.gemspec b/authentication-zero.gemspec index 5b886f5b..bf13f7c2 100644 --- a/authentication-zero.gemspec +++ b/authentication-zero.gemspec @@ -19,4 +19,7 @@ Gem::Specification.new do |spec| spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } end + + # For translations, depend on the i18n gem + spec.add_dependency "i18n", ">= 7.0" end diff --git a/lib/authentication_zero.rb b/lib/authentication_zero.rb index 6018ed2c..4a3be5de 100644 --- a/lib/authentication_zero.rb +++ b/lib/authentication_zero.rb @@ -1,4 +1,7 @@ require "authentication_zero/version" +require "i18n" module AuthenticationZero + # Load translations when gem is loaded + I18n.load_path += Dir[File.expand_path("locales/*.yml", __dir__)] end diff --git a/lib/authentication_zero/locales/en.yml b/lib/authentication_zero/locales/en.yml new file mode 100644 index 00000000..fee9673c --- /dev/null +++ b/lib/authentication_zero/locales/en.yml @@ -0,0 +1,2 @@ +en: + authentication_zero: \ No newline at end of file From 9b1cffd5927d11cafd3aa6065395c541b9c489d3 Mon Sep 17 00:00:00 2001 From: Benedikt Laube Date: Tue, 21 Oct 2025 10:17:59 +0200 Subject: [PATCH 02/13] Use semantic version for i18n dependency --- authentication-zero-4.0.4.gem | Bin 0 -> 29184 bytes authentication-zero.gemspec | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 authentication-zero-4.0.4.gem diff --git a/authentication-zero-4.0.4.gem b/authentication-zero-4.0.4.gem new file mode 100644 index 0000000000000000000000000000000000000000..63eb76bc3fa670d58ccada5cca424e76831ae6d9 GIT binary patch literal 29184 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 Yz4{+nivJe*ZwLO{f&X^kf3ySt3+ycaod5s; literal 0 HcmV?d00001 diff --git a/authentication-zero.gemspec b/authentication-zero.gemspec index bf13f7c2..b26a0040 100644 --- a/authentication-zero.gemspec +++ b/authentication-zero.gemspec @@ -21,5 +21,5 @@ Gem::Specification.new do |spec| end # For translations, depend on the i18n gem - spec.add_dependency "i18n", ">= 7.0" + spec.add_dependency "i18n", "~> 7.0" end From aa73849cc6c41864f9ba6ce08579488a65096237 Mon Sep 17 00:00:00 2001 From: Benedikt Laube Date: Tue, 21 Oct 2025 10:18:33 +0200 Subject: [PATCH 03/13] Remove build --- authentication-zero-4.0.4.gem | Bin 29184 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 authentication-zero-4.0.4.gem diff --git a/authentication-zero-4.0.4.gem b/authentication-zero-4.0.4.gem deleted file mode 100644 index 63eb76bc3fa670d58ccada5cca424e76831ae6d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29184 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 Yz4{+nivJe*ZwLO{f&X^kf3ySt3+ycaod5s; From 92314ac7d84762aa4d6e78a16b7b503c7bf7e90e Mon Sep 17 00:00:00 2001 From: Benedikt Laube Date: Tue, 21 Oct 2025 10:46:59 +0200 Subject: [PATCH 04/13] Use i18n decorators in erb templates --- lib/authentication_zero/locales/en.yml | 182 +++++++++++++++++- .../authentications/events/index.html.erb.tt | 12 +- .../templates/erb/home/index.html.erb.tt | 26 +-- .../erb/identity/emails/edit.html.erb.tt | 16 +- .../identity/password_resets/edit.html.erb.tt | 10 +- .../identity/password_resets/new.html.erb.tt | 4 +- .../templates/erb/invitations/new.html.erb.tt | 6 +- .../templates/erb/passwords/edit.html.erb.tt | 14 +- .../erb/registrations/new.html.erb.tt | 6 +- .../templates/erb/sessions/index.html.erb.tt | 12 +- .../templates/erb/sessions/new.html.erb.tt | 12 +- .../sessions/passwordlesses/new.html.erb.tt | 4 +- .../erb/sessions/sudos/new.html.erb.tt | 12 +- .../challenge/recovery_codes/new.html.erb.tt | 6 +- .../challenge/security_keys/new.html.erb.tt | 6 +- .../challenge/totps/new.html.erb.tt | 10 +- .../profile/recovery_codes/index.html.erb.tt | 12 +- .../security_keys/_form_confirm.html.erb.tt | 8 +- .../security_keys/_form_edit.html.erb.tt | 8 +- .../profile/security_keys/edit.html.erb.tt | 2 +- .../profile/security_keys/index.html.erb.tt | 8 +- .../profile/security_keys/new.html.erb.tt | 6 +- .../profile/totps/new.html.erb.tt | 28 +-- .../email_verification.html.erb.tt | 10 +- .../invitation_instructions.html.erb.tt | 10 +- .../user_mailer/password_reset.html.erb.tt | 10 +- .../erb/user_mailer/passwordless.html.erb.tt | 8 +- 27 files changed, 314 insertions(+), 134 deletions(-) diff --git a/lib/authentication_zero/locales/en.yml b/lib/authentication_zero/locales/en.yml index fee9673c..64020f45 100644 --- a/lib/authentication_zero/locales/en.yml +++ b/lib/authentication_zero/locales/en.yml @@ -1,2 +1,182 @@ en: - authentication_zero: \ No newline at end of file + authentication_zero: + home: + index: + signed_as: "Signed as %{email}" + login_and_verification: "Login and verification" + change_password: "Change password" + change_email_address: "Change email address" + two_factor_authentication: "Two-Factor Authentication" + recovery_codes: "Recovery Codes" + security_keys: "Security keys" + send_invitation: "Send invitation" + signin_as_last_user: "Signin as last user" + access_history: "Access history" + devices_sessions: "Devices & Sessions" + activity_log: "Activity Log" + log_out: "Log out" + authentications: + events: + index: + activity_log: "Activity Log" + user_agent: "User Agent:" + action: "Action:" + ip_address: "IP Address:" + created_at: "Created at:" + back: "Back" + identity: + emails: + edit: + change_your_email: "Change your email" + verify_your_email: "Verify your email" + verification_sent: "We sent a verification email to the address below. Check that email and follow those instructions to confirm it's your email address." + re_send_verification_email: "Re-send verification email" + new_email: "New email" + password_challenge: "Password challenge" + save_changes: "Save changes" + back: "Back" + password_resets: + edit: + reset_your_password: "Reset your password" + new_password: "New password" + confirm_new_password: "Confirm new password" + password_minimum: "12 characters minimum." + save_changes: "Save changes" + new: + forgot_your_password: "Forgot your password?" + send_password_reset_email: "Send password reset email" + invitations: + new: + send_invitation: "Send invitation" + send_an_invitation: "Send an invitation" + back: "Back" + passwords: + edit: + change_your_password: "Change your password" + new_password: "New password" + confirm_new_password: "Confirm new password" + password_minimum: "12 characters minimum." + save_changes: "Save changes" + back: "Back" + registrations: + new: + sign_up: "Sign up" + password_minimum: "12 characters minimum." + sessions: + index: + devices_sessions: "Devices & Sessions" + user_agent: "User Agent:" + ip_address: "Ip Address:" + created_at: "Created at:" + log_out: "Log out" + back: "Back" + new: + sign_in: "Sign in" + sign_in_without_password: "Sign in without password" + sign_in_with_omniauth: "Sign in with OmniAuth" + sign_up: "Sign up" + forgot_your_password: "Forgot your password?" + passwordlesses: + new: + sign_in_without_password: "Sign in without password" + sign_in: "Sign in" + sudos: + new: + enter_password_to_continue: "Enter your password to continue" + continue: "Continue" + why_asking: "Why are you asking me to do this?" + protection_explanation: "To better protect your account, we'll occasionally ask you to confirm your password before performing sensitive actions." + forgot_password: "Forgot your password?" + reset_help: "We'll help you %{link} so you can continue." + reset_link_text: "reset it" + two_factor_authentication: + challenge: + recovery_codes: + new: + enter_recovery_code: "OK, enter one of your recovery codes below:" + continue: "Continue" + access_instructions: "To access your account, enter one of the recovery codes (e.g., xxxxxxxxxx) you saved when you set up your two-factor authentication device." + security_keys: + new: + verify_with_security_key: "Verify with your security key." + use_security_key: "Use security key" + security_key_instructions: "Have your security key ready. If it's the USB kind insert it now and then, if it has one, press the activation button when asked." + totps: + new: + enter_2fa_code: "Next, open the 2FA authenticator app on your phone and type the six digit code below:" + verify: "Verify" + dont_have_phone: "Don't have your phone?" + use_recovery_code: "Use a recovery code to access your account." + use_security_key: "Use a security key to access your account." + profile: + recovery_codes: + index: + two_factor_recovery_codes: "Two-factor recovery codes" + recovery_codes_description: "Recovery codes provide a way to log in if you lose your phone (or don't have it with you). Save these and keep them somewhere safe." + ok_done: "OK, I'm done" + need_new_codes: "Need new recovery codes?" + new_codes_warning: "If you think your codes have fallen into the wrong hands, you can get a new set. Be sure to save the new ones because the old codes will stop working." + generate_new_codes: "Generate new recovery codes" + security_keys: + _form_confirm: + one_more_step: "One more step. Please give this security key a nickname to help you remember it." + name: "Name" + example: "e.g., Macbook Touch ID" + save: "Save" + _form_edit: + name: "Name" + example: "e.g., Macbook Touch ID" + save_changes: "Save changes" + remove_security_key: "Remove this security key..." + edit: + edit_security_key: "Edit security key" + index: + security_keys: "Security keys" + security_keys_description: "A security key is a hardware device used to verify your identity. For example, a built-in fingerprint reader, a plug-in USB key, or a login system like Windows Hello." + add_security_key: "Add security key" + back: "Back" + new: + add_security_key: "Add a security key" + ready_instructions: "Have your security key ready. If it's the USB kind insert it now and then, if it has one, press the activation button when asked." + im_ready: "I'm ready, let's go" + totps: + new: + replace_existing_2fa: "Want to replace your existing 2FA setup?" + already_protected: "Your account is already protected with two-factor authentication. You can replace that setup if you want to switch to a new phone or authenticator app." + continue_warning: "Do you want to continue? Your existing 2FA setup will no longer work." + yes_replace: "Yes, replace my 2FA setup" + upgrade_security: "Upgrade your security with 2FA" + step1_get_app: "Step 1: Get an Authenticator App" + get_app_instructions: "First, you'll need a 2FA authenticator app on your phone. %{strong_text}" + skip_if_have: "If you already have one, skip to step 2." + recommend_app: "If you don't have one, or you aren't sure, we recommend Microsoft Authenticator. You can download it free on the Apple App Store for iPhone, or Google Play Store for Android. Please grab your phone, search the store, and install it now." + step2_scan_enter: "Step 2: Scan + Enter the Code" + scan_instructions: "Next, open the authenticator app, tap \"Scan QR code\" or \"+\", and, when it asks, point your phone's camera at this QR code picture below." + point_camera: "Point your camera here" + enter_code_instructions: "After scanning with your camera, the app will generate a six-digit code. Enter it here:" + verify_activate: "Verify and activate" + back: "Back" + user_mailer: + email_verification: + greeting: "Hey there," + confirmation_text: "This is to confirm that %{email} is the email you want to use on your account. If you ever lose your password, that's where we'll email a reset link." + must_confirm: "You must hit the link below to confirm that you received this email." + confirm_link: "Yes, use this email for my account" + help_text: "Have questions or need help? Just reply to this email and our support team will help you sort it out." + invitation_instructions: + greeting: "Hey there," + invitation_text: "Someone has invited you to the application, you can accept it through the link below." + accept_invitation: "Accept invitation" + ignore_text: "If you don't want to accept the invitation, please ignore this email. Your account won't be created until you access the link above and set your password." + help_text: "Have questions or need help? Just reply to this email and our support team will help you sort it out." + password_reset: + greeting: "Hey there," + reset_text: "Can't remember your password for %{email}? That's OK, it happens. Just hit the link below to set a new one." + reset_link: "Reset my password" + ignore_text: "If you did not request a password reset you can safely ignore this email, it expires in 20 minutes. Only someone with access to this email account can reset your password." + help_text: "Have questions or need help? Just reply to this email and our support team will help you sort it out." + passwordless: + greeting: "Hey there," + magic_link_text: "You requested a magic sign-in link. Here you go:" + sign_in_link: "Sign in without password" + help_text: "Have questions or need help? Just reply to this email and our support team will help you sort it out." \ No newline at end of file diff --git a/lib/generators/authentication/templates/erb/authentications/events/index.html.erb.tt b/lib/generators/authentication/templates/erb/authentications/events/index.html.erb.tt index 0703cca7..b02eda89 100644 --- a/lib/generators/authentication/templates/erb/authentications/events/index.html.erb.tt +++ b/lib/generators/authentication/templates/erb/authentications/events/index.html.erb.tt @@ -1,25 +1,25 @@ -

Activity Log

+

<%%= t('authentication_zero.authentications.events.index.activity_log') %>

<%% @events.each do |event| %>

- User Agent: + <%%= t('authentication_zero.authentications.events.index.user_agent') %> <%%= event.user_agent %>

- Action: + <%%= t('authentication_zero.authentications.events.index.action') %> <%%= event.action %>

- Ip Address: + <%%= t('authentication_zero.authentications.events.index.ip_address') %> <%%= event.ip_address %>

- Created at: + <%%= t('authentication_zero.authentications.events.index.created_at') %> <%%= event.created_at %>

@@ -29,5 +29,5 @@
- <%%= link_to "Back", root_path %> + <%%= link_to t('authentication_zero.authentications.events.index.back'), root_path %>
diff --git a/lib/generators/authentication/templates/erb/home/index.html.erb.tt b/lib/generators/authentication/templates/erb/home/index.html.erb.tt index 40b0e540..bc31cf4c 100644 --- a/lib/generators/authentication/templates/erb/home/index.html.erb.tt +++ b/lib/generators/authentication/templates/erb/home/index.html.erb.tt @@ -1,48 +1,48 @@

<%%= notice %>

-

Signed as <%%= Current.user.email %>

+

<%%= t('authentication_zero.home.index.signed_as', email: Current.user.email) %>

-

Login and verification

+

<%%= t('authentication_zero.home.index.login_and_verification') %>

- <%%= link_to "Change password", edit_password_path %> + <%%= link_to t('authentication_zero.home.index.change_password'), edit_password_path %>
- <%%= link_to "Change email address", edit_identity_email_path %> + <%%= link_to t('authentication_zero.home.index.change_email_address'), edit_identity_email_path %>
<%- if two_factor? %>
- <%%= link_to "Two-Factor Authentication", new_two_factor_authentication_profile_totp_path %> + <%%= link_to t('authentication_zero.home.index.two_factor_authentication'), new_two_factor_authentication_profile_totp_path %>
<%% if Current.user.otp_required_for_sign_in? %> -
<%%= link_to "Recovery Codes", two_factor_authentication_profile_recovery_codes_path %>
+
<%%= link_to t('authentication_zero.home.index.recovery_codes'), two_factor_authentication_profile_recovery_codes_path %>
<%- if webauthn? -%> -
<%%= link_to "Security keys", two_factor_authentication_profile_security_keys_path %>
+
<%%= link_to t('authentication_zero.home.index.security_keys'), two_factor_authentication_profile_security_keys_path %>
<%- end -%> <%% end %> <%- end -%> <%- if invitable? %>
- <%%= link_to "Send invitation", new_invitation_path %> + <%%= link_to t('authentication_zero.home.index.send_invitation'), new_invitation_path %>
<%- end -%> <%- if masqueradable? %> -<%%= button_to "Signin as last user", user_masquerade_path(User.last) %> +<%%= button_to t('authentication_zero.home.index.signin_as_last_user'), user_masquerade_path(User.last) %> <%- end -%> -

Access history

+

<%%= t('authentication_zero.home.index.access_history') %>

- <%%= link_to "Devices & Sessions", sessions_path %> + <%%= link_to t('authentication_zero.home.index.devices_sessions'), sessions_path %>
<%- if options.trackable? %>
- <%%= link_to "Activity Log", authentications_events_path %> + <%%= link_to t('authentication_zero.home.index.activity_log'), authentications_events_path %>
<%- end -%>
-<%%= button_to "Log out", Current.session, method: :delete %> +<%%= button_to t('authentication_zero.home.index.log_out'), Current.session, method: :delete %> diff --git a/lib/generators/authentication/templates/erb/identity/emails/edit.html.erb.tt b/lib/generators/authentication/templates/erb/identity/emails/edit.html.erb.tt index b0fd041d..ee89f305 100644 --- a/lib/generators/authentication/templates/erb/identity/emails/edit.html.erb.tt +++ b/lib/generators/authentication/templates/erb/identity/emails/edit.html.erb.tt @@ -1,11 +1,11 @@

<%%= alert %>

<%% if Current.user.verified? %> -

Change your email

+

<%%= t('authentication_zero.identity.emails.edit.change_your_email') %>

<%% else %> -

Verify your email

-

We sent a verification email to the address below. Check that email and follow those instructions to confirm it's your email address.

-

<%%= button_to "Re-send verification email", identity_email_verification_path %>

+

<%%= t('authentication_zero.identity.emails.edit.verify_your_email') %>

+

<%%= t('authentication_zero.identity.emails.edit.verification_sent') %>

+

<%%= button_to t('authentication_zero.identity.emails.edit.re_send_verification_email'), identity_email_verification_path %>

<%% end %> <%%= form_with(url: identity_email_path, method: :patch) do |form| %> @@ -22,22 +22,22 @@ <%% end %>
- <%%= form.label :email, "New email", style: "display: block" %> + <%%= form.label :email, t('authentication_zero.identity.emails.edit.new_email'), style: "display: block" %> <%%= form.email_field :email, required: true, autofocus: true %>
- <%%= form.label :password_challenge, style: "display: block" %> + <%%= form.label :password_challenge, t('authentication_zero.identity.emails.edit.password_challenge'), style: "display: block" %> <%%= form.password_field :password_challenge, required: true, autocomplete: "current-password" %>
- <%%= form.submit "Save changes" %> + <%%= form.submit t('authentication_zero.identity.emails.edit.save_changes') %>
<%% end %>
- <%%= link_to "Back", root_path %> + <%%= link_to t('authentication_zero.identity.emails.edit.back'), root_path %>
diff --git a/lib/generators/authentication/templates/erb/identity/password_resets/edit.html.erb.tt b/lib/generators/authentication/templates/erb/identity/password_resets/edit.html.erb.tt index 505a7773..30060188 100644 --- a/lib/generators/authentication/templates/erb/identity/password_resets/edit.html.erb.tt +++ b/lib/generators/authentication/templates/erb/identity/password_resets/edit.html.erb.tt @@ -1,4 +1,4 @@ -

Reset your password

+

<%%= t('authentication_zero.identity.password_resets.edit.reset_your_password') %>

<%%= form_with(url: identity_password_reset_path, method: :patch) do |form| %> <%% if @user.errors.any? %> @@ -16,17 +16,17 @@ <%%= form.hidden_field :sid, value: params[:sid] %>
- <%%= form.label :password, "New password", style: "display: block" %> + <%%= form.label :password, t('authentication_zero.identity.password_resets.edit.new_password'), style: "display: block" %> <%%= form.password_field :password, required: true, autofocus: true, autocomplete: "new-password" %> -
12 characters minimum.
+
<%%= t('authentication_zero.identity.password_resets.edit.password_minimum') %>
- <%%= form.label :password_confirmation, "Confirm new password", style: "display: block" %> + <%%= form.label :password_confirmation, t('authentication_zero.identity.password_resets.edit.confirm_new_password'), style: "display: block" %> <%%= form.password_field :password_confirmation, required: true, autocomplete: "new-password" %>
- <%%= form.submit "Save changes" %> + <%%= form.submit t('authentication_zero.identity.password_resets.edit.save_changes') %>
<%% end %> diff --git a/lib/generators/authentication/templates/erb/identity/password_resets/new.html.erb.tt b/lib/generators/authentication/templates/erb/identity/password_resets/new.html.erb.tt index f67ae663..c58c564f 100644 --- a/lib/generators/authentication/templates/erb/identity/password_resets/new.html.erb.tt +++ b/lib/generators/authentication/templates/erb/identity/password_resets/new.html.erb.tt @@ -1,6 +1,6 @@

<%%= alert %>

-

Forgot your password?

+

<%%= t('authentication_zero.identity.password_resets.new.forgot_your_password') %>

<%%= form_with(url: identity_password_reset_path) do |form| %>
@@ -9,6 +9,6 @@
- <%%= form.submit "Send password reset email" %> + <%%= form.submit t('authentication_zero.identity.password_resets.new.send_password_reset_email') %>
<%% end %> diff --git a/lib/generators/authentication/templates/erb/invitations/new.html.erb.tt b/lib/generators/authentication/templates/erb/invitations/new.html.erb.tt index 43218cf6..267620f5 100644 --- a/lib/generators/authentication/templates/erb/invitations/new.html.erb.tt +++ b/lib/generators/authentication/templates/erb/invitations/new.html.erb.tt @@ -1,6 +1,6 @@

<%%= notice %>

-

Send invitation

+

<%%= t('authentication_zero.invitations.new.send_invitation') %>

<%%= form_with(url: invitation_path) do |form| %> <%% if @user.errors.any? %> @@ -21,12 +21,12 @@
- <%%= form.submit "Send an invitation" %> + <%%= form.submit t('authentication_zero.invitations.new.send_an_invitation') %>
<%% end %>
- <%%= link_to "Back", root_path %> + <%%= link_to t('authentication_zero.invitations.new.back'), root_path %>
diff --git a/lib/generators/authentication/templates/erb/passwords/edit.html.erb.tt b/lib/generators/authentication/templates/erb/passwords/edit.html.erb.tt index c4ba536f..46237f0a 100644 --- a/lib/generators/authentication/templates/erb/passwords/edit.html.erb.tt +++ b/lib/generators/authentication/templates/erb/passwords/edit.html.erb.tt @@ -1,6 +1,6 @@

<%%= alert %>

-

Change your password

+

<%%= t('authentication_zero.passwords.edit.change_your_password') %>

<%%= form_with(url: password_path, method: :patch) do |form| %> <%% if @user.errors.any? %> @@ -16,28 +16,28 @@ <%% end %>
- <%%= form.label :password_challenge, style: "display: block" %> + <%%= form.label :password_challenge, t('authentication_zero.passwords.edit.password_challenge'), style: "display: block" %> <%%= form.password_field :password_challenge, required: true, autofocus: true, autocomplete: "current-password" %>
- <%%= form.label :password, "New password", style: "display: block" %> + <%%= form.label :password, t('authentication_zero.passwords.edit.new_password'), style: "display: block" %> <%%= form.password_field :password, required: true, autocomplete: "new-password" %> -
12 characters minimum.
+
<%%= t('authentication_zero.passwords.edit.password_minimum') %>
- <%%= form.label :password_confirmation, "Confirm new password", style: "display: block" %> + <%%= form.label :password_confirmation, t('authentication_zero.passwords.edit.confirm_new_password'), style: "display: block" %> <%%= form.password_field :password_confirmation, required: true, autocomplete: "new-password" %>
- <%%= form.submit "Save changes" %> + <%%= form.submit t('authentication_zero.passwords.edit.save_changes') %>
<%% end %>
- <%%= link_to "Back", root_path %> + <%%= link_to t('authentication_zero.passwords.edit.back'), root_path %>
diff --git a/lib/generators/authentication/templates/erb/registrations/new.html.erb.tt b/lib/generators/authentication/templates/erb/registrations/new.html.erb.tt index 39465697..0a46b57d 100644 --- a/lib/generators/authentication/templates/erb/registrations/new.html.erb.tt +++ b/lib/generators/authentication/templates/erb/registrations/new.html.erb.tt @@ -1,4 +1,4 @@ -

Sign up

+

<%%= t('authentication_zero.registrations.new.sign_up') %>

<%%= form_with(url: sign_up_path) do |form| %> <%% if @user.errors.any? %> @@ -21,7 +21,7 @@
<%%= form.label :password, style: "display: block" %> <%%= form.password_field :password, required: true, autocomplete: "new-password" %> -
12 characters minimum.
+
<%%= t('authentication_zero.registrations.new.password_minimum') %>
@@ -30,6 +30,6 @@
- <%%= form.submit "Sign up" %> + <%%= form.submit t('authentication_zero.registrations.new.sign_up') %>
<%% end %> diff --git a/lib/generators/authentication/templates/erb/sessions/index.html.erb.tt b/lib/generators/authentication/templates/erb/sessions/index.html.erb.tt index c6742fe4..bc8daa03 100644 --- a/lib/generators/authentication/templates/erb/sessions/index.html.erb.tt +++ b/lib/generators/authentication/templates/erb/sessions/index.html.erb.tt @@ -1,28 +1,28 @@

<%%= notice %>

-

Devices & Sessions

+

<%%= t('authentication_zero.sessions.index.devices_sessions') %>

<%% @sessions.each do |session| %>

- User Agent: + <%%= t('authentication_zero.sessions.index.user_agent') %> <%%= session.user_agent %>

- Ip Address: + <%%= t('authentication_zero.sessions.index.ip_address') %> <%%= session.ip_address %>

- Created at: + <%%= t('authentication_zero.sessions.index.created_at') %> <%%= session.created_at %>

- <%%= button_to "Log out", session, method: :delete %> + <%%= button_to t('authentication_zero.sessions.index.log_out'), session, method: :delete %>

<%% end %>
@@ -30,5 +30,5 @@
- <%%= link_to "Back", root_path %> + <%%= link_to t('authentication_zero.sessions.index.back'), root_path %>
diff --git a/lib/generators/authentication/templates/erb/sessions/new.html.erb.tt b/lib/generators/authentication/templates/erb/sessions/new.html.erb.tt index 05dc2669..9f48f195 100644 --- a/lib/generators/authentication/templates/erb/sessions/new.html.erb.tt +++ b/lib/generators/authentication/templates/erb/sessions/new.html.erb.tt @@ -1,7 +1,7 @@

<%%= notice %>

<%%= alert %>

-

Sign in

+

<%%= t('authentication_zero.sessions.new.sign_in') %>

<%%= form_with(url: sign_in_path) do |form| %>
@@ -15,7 +15,7 @@
- <%%= form.submit "Sign in" %> + <%%= form.submit t('authentication_zero.sessions.new.sign_in') %>
<%% end %> @@ -23,18 +23,18 @@ <%- if passwordless? %>
- <%%= link_to "Sign in without password", new_sessions_passwordless_path %> + <%%= link_to t('authentication_zero.sessions.new.sign_in_without_password'), new_sessions_passwordless_path %>
<%- end -%> <%- if omniauthable? %>
- <%%= button_to "Sign in with OmniAuth", "/auth/developer", "data-turbo" => false %> + <%%= button_to t('authentication_zero.sessions.new.sign_in_with_omniauth'), "/auth/developer", "data-turbo" => false %>
<%- end -%>
- <%%= link_to "Sign up", sign_up_path %> | - <%%= link_to "Forgot your password?", new_identity_password_reset_path %> + <%%= link_to t('authentication_zero.sessions.new.sign_up'), sign_up_path %> | + <%%= link_to t('authentication_zero.sessions.new.forgot_your_password'), new_identity_password_reset_path %>
diff --git a/lib/generators/authentication/templates/erb/sessions/passwordlesses/new.html.erb.tt b/lib/generators/authentication/templates/erb/sessions/passwordlesses/new.html.erb.tt index f09b4a78..daf221aa 100644 --- a/lib/generators/authentication/templates/erb/sessions/passwordlesses/new.html.erb.tt +++ b/lib/generators/authentication/templates/erb/sessions/passwordlesses/new.html.erb.tt @@ -1,6 +1,6 @@

<%%= alert %>

-

Sign in without password

+

<%%= t('authentication_zero.sessions.passwordlesses.new.sign_in_without_password') %>

<%%= form_with(url: sessions_passwordless_path) do |form| %>
@@ -9,6 +9,6 @@
- <%%= form.submit "Sign in" %> + <%%= form.submit t('authentication_zero.sessions.passwordlesses.new.sign_in') %>
<%% end %> diff --git a/lib/generators/authentication/templates/erb/sessions/sudos/new.html.erb.tt b/lib/generators/authentication/templates/erb/sessions/sudos/new.html.erb.tt index 1f8ae679..04f1f79f 100644 --- a/lib/generators/authentication/templates/erb/sessions/sudos/new.html.erb.tt +++ b/lib/generators/authentication/templates/erb/sessions/sudos/new.html.erb.tt @@ -1,6 +1,6 @@

<%%= alert %>

-

Enter your password to continue

+

<%%= t('authentication_zero.sessions.sudos.new.enter_password_to_continue') %>

<%%= form_with(url: sessions_sudo_path) do |form| %> @@ -11,18 +11,18 @@
- <%%= form.submit "Continue" %> + <%%= form.submit t('authentication_zero.sessions.sudos.new.continue') %>
<%% end %>

- Why are you asking me to do this?
- To better protect your account, we'll occasionally ask you to confirm your password before performing sensitive actions. + <%%= t('authentication_zero.sessions.sudos.new.why_asking') %>
+ <%%= t('authentication_zero.sessions.sudos.new.protection_explanation') %>

- Forgot your password?
- We'll help you <%%= link_to "reset it", new_identity_password_reset_path %> so you can continue. + <%%= t('authentication_zero.sessions.sudos.new.forgot_password') %>
+ <%%= t('authentication_zero.sessions.sudos.new.reset_help', link: link_to(t('authentication_zero.sessions.sudos.new.reset_link_text'), new_identity_password_reset_path)) %>

diff --git a/lib/generators/authentication/templates/erb/two_factor_authentication/challenge/recovery_codes/new.html.erb.tt b/lib/generators/authentication/templates/erb/two_factor_authentication/challenge/recovery_codes/new.html.erb.tt index 20f50465..69187bc4 100644 --- a/lib/generators/authentication/templates/erb/two_factor_authentication/challenge/recovery_codes/new.html.erb.tt +++ b/lib/generators/authentication/templates/erb/two_factor_authentication/challenge/recovery_codes/new.html.erb.tt @@ -3,16 +3,16 @@ <%%= form_with(url: two_factor_authentication_challenge_recovery_codes_path) do |form| %>
<%%= form.label :code do %> -

OK, enter one of your recovery codes below:

+

<%%= t('authentication_zero.two_factor_authentication.challenge.recovery_codes.new.enter_recovery_code') %>

<%% end %> <%%= form.text_field :code, autofocus: true, required: true, autocomplete: :off %>
- <%%= form.submit "Continue" %> + <%%= form.submit t('authentication_zero.two_factor_authentication.challenge.recovery_codes.new.continue') %>
<%% end %>
-

To access your account, enter one of the recovery codes (e.g., xxxxxxxxxx) you saved when you set up your two-factor authentication device.

+

<%%= t('authentication_zero.two_factor_authentication.challenge.recovery_codes.new.access_instructions') %>

diff --git a/lib/generators/authentication/templates/erb/two_factor_authentication/challenge/security_keys/new.html.erb.tt b/lib/generators/authentication/templates/erb/two_factor_authentication/challenge/security_keys/new.html.erb.tt index ba9fa902..653efece 100644 --- a/lib/generators/authentication/templates/erb/two_factor_authentication/challenge/security_keys/new.html.erb.tt +++ b/lib/generators/authentication/templates/erb/two_factor_authentication/challenge/security_keys/new.html.erb.tt @@ -6,7 +6,7 @@ -

Verify with your security key.

- <%%= button_tag "Use security key", type: :button, data: { web_authn_target: "button", action: "web-authn#getCredential" } %> -

Have your security key ready. If it's the USB kind insert it now and then, if it has one, press the activation button when asked.

+

<%%= t('authentication_zero.two_factor_authentication.challenge.security_keys.new.verify_with_security_key') %>

+ <%%= button_tag t('authentication_zero.two_factor_authentication.challenge.security_keys.new.use_security_key'), type: :button, data: { web_authn_target: "button", action: "web-authn#getCredential" } %> +

<%%= t('authentication_zero.two_factor_authentication.challenge.security_keys.new.security_key_instructions') %>

diff --git a/lib/generators/authentication/templates/erb/two_factor_authentication/challenge/totps/new.html.erb.tt b/lib/generators/authentication/templates/erb/two_factor_authentication/challenge/totps/new.html.erb.tt index d2b0ffcf..c8fdf7d6 100644 --- a/lib/generators/authentication/templates/erb/two_factor_authentication/challenge/totps/new.html.erb.tt +++ b/lib/generators/authentication/templates/erb/two_factor_authentication/challenge/totps/new.html.erb.tt @@ -3,22 +3,22 @@ <%%= form_with(url: two_factor_authentication_challenge_totp_path) do |form| %>
<%%= form.label :code do %> -

Next, open the 2FA authenticator app on your phone and type the six digit code below:

+

<%%= t('authentication_zero.two_factor_authentication.challenge.totps.new.enter_2fa_code') %>

<%% end %> <%%= form.text_field :code, autofocus: true, required: true, autocomplete: :off %>
- <%%= form.submit "Verify" %> + <%%= form.submit t('authentication_zero.two_factor_authentication.challenge.totps.new.verify') %>
<%% end %>
-

Don't have your phone?

-
<%%= link_to "Use a recovery code to access your account.", new_two_factor_authentication_challenge_recovery_codes_path %>
+

<%%= t('authentication_zero.two_factor_authentication.challenge.totps.new.dont_have_phone') %>

+
<%%= link_to t('authentication_zero.two_factor_authentication.challenge.totps.new.use_recovery_code'), new_two_factor_authentication_challenge_recovery_codes_path %>
<%- if webauthn? %> <%% if @user.security_keys.exists? %> -
<%%= link_to "Use a security key to access your account.", new_two_factor_authentication_challenge_security_keys_path %>
+
<%%= link_to t('authentication_zero.two_factor_authentication.challenge.totps.new.use_security_key'), new_two_factor_authentication_challenge_security_keys_path %>
<%% end %> <%- end -%>
diff --git a/lib/generators/authentication/templates/erb/two_factor_authentication/profile/recovery_codes/index.html.erb.tt b/lib/generators/authentication/templates/erb/two_factor_authentication/profile/recovery_codes/index.html.erb.tt index 15518cdf..1fc18e79 100644 --- a/lib/generators/authentication/templates/erb/two_factor_authentication/profile/recovery_codes/index.html.erb.tt +++ b/lib/generators/authentication/templates/erb/two_factor_authentication/profile/recovery_codes/index.html.erb.tt @@ -1,16 +1,16 @@

<%%= notice %>

-

Two-factor recovery codes

-

Recovery codes provide a way to log in if you lose your phone (or don't have it with you). Save these and keep them somewhere safe.

+

<%%= t('authentication_zero.two_factor_authentication.profile.recovery_codes.index.two_factor_recovery_codes') %>

+

<%%= t('authentication_zero.two_factor_authentication.profile.recovery_codes.index.recovery_codes_description') %>

    <%%= render @recovery_codes %>
-
<%%= link_to "OK, I'm done", root_path %>
+
<%%= link_to t('authentication_zero.two_factor_authentication.profile.recovery_codes.index.ok_done'), root_path %>

-

Need new recovery codes?

+

<%%= t('authentication_zero.two_factor_authentication.profile.recovery_codes.index.need_new_codes') %>

-

If you think your codes have fallen into the wrong hands, you can get a new set. Be sure to save the new ones because the old codes will stop working.

+

<%%= t('authentication_zero.two_factor_authentication.profile.recovery_codes.index.new_codes_warning') %>

-<%%= button_to "Generate new recovery codes", two_factor_authentication_profile_recovery_codes_path %> +<%%= button_to t('authentication_zero.two_factor_authentication.profile.recovery_codes.index.generate_new_codes'), two_factor_authentication_profile_recovery_codes_path %> diff --git a/lib/generators/authentication/templates/erb/two_factor_authentication/profile/security_keys/_form_confirm.html.erb.tt b/lib/generators/authentication/templates/erb/two_factor_authentication/profile/security_keys/_form_confirm.html.erb.tt index 372aec6f..c59bbf94 100644 --- a/lib/generators/authentication/templates/erb/two_factor_authentication/profile/security_keys/_form_confirm.html.erb.tt +++ b/lib/generators/authentication/templates/erb/two_factor_authentication/profile/security_keys/_form_confirm.html.erb.tt @@ -1,13 +1,13 @@ <%%= form_with(url: two_factor_authentication_profile_security_key_path, method: :patch) do |form| %> -

One more step. Please give this security key a nickname to help you remember it.

+

<%%= t('authentication_zero.two_factor_authentication.profile.security_keys._form_confirm.one_more_step') %>

- <%%= form.label :name, style: "display: block" %> + <%%= form.label :name, t('authentication_zero.two_factor_authentication.profile.security_keys._form_confirm.name'), style: "display: block" %> <%%= form.text_field :name, autofocus: true, required: true %> -
e.g., Macbook Touch ID
+
<%%= t('authentication_zero.two_factor_authentication.profile.security_keys._form_confirm.example') %>
- <%%= form.submit "Save" %> + <%%= form.submit t('authentication_zero.two_factor_authentication.profile.security_keys._form_confirm.save') %>
<%% end %> diff --git a/lib/generators/authentication/templates/erb/two_factor_authentication/profile/security_keys/_form_edit.html.erb.tt b/lib/generators/authentication/templates/erb/two_factor_authentication/profile/security_keys/_form_edit.html.erb.tt index f6a7f20a..7a9357ac 100644 --- a/lib/generators/authentication/templates/erb/two_factor_authentication/profile/security_keys/_form_edit.html.erb.tt +++ b/lib/generators/authentication/templates/erb/two_factor_authentication/profile/security_keys/_form_edit.html.erb.tt @@ -1,17 +1,17 @@ <%%= form_with(url: two_factor_authentication_profile_security_key_path, method: :patch) do |form| %>
- <%%= form.label :name, style: "display: block" %> + <%%= form.label :name, t('authentication_zero.two_factor_authentication.profile.security_keys._form_edit.name'), style: "display: block" %> <%%= form.text_field :name, value: @security_key.name, autofocus: true, required: true %> -
e.g., Macbook Touch ID
+
<%%= t('authentication_zero.two_factor_authentication.profile.security_keys._form_edit.example') %>
- <%%= form.submit "Save changes" %> + <%%= form.submit t('authentication_zero.two_factor_authentication.profile.security_keys._form_edit.save_changes') %>
<%% end %>
- <%%= button_to "Remove this security key...", two_factor_authentication_profile_security_key_path(@security_key), method: :delete %> + <%%= button_to t('authentication_zero.two_factor_authentication.profile.security_keys._form_edit.remove_security_key'), two_factor_authentication_profile_security_key_path(@security_key), method: :delete %>
diff --git a/lib/generators/authentication/templates/erb/two_factor_authentication/profile/security_keys/edit.html.erb.tt b/lib/generators/authentication/templates/erb/two_factor_authentication/profile/security_keys/edit.html.erb.tt index 7fcc0f8e..7bde2031 100644 --- a/lib/generators/authentication/templates/erb/two_factor_authentication/profile/security_keys/edit.html.erb.tt +++ b/lib/generators/authentication/templates/erb/two_factor_authentication/profile/security_keys/edit.html.erb.tt @@ -1,3 +1,3 @@ -

Edit security key

+

<%%= t('authentication_zero.two_factor_authentication.profile.security_keys.edit.edit_security_key') %>

<%%= render params[:confirmation] ? "form_confirm" : "form_edit" %> diff --git a/lib/generators/authentication/templates/erb/two_factor_authentication/profile/security_keys/index.html.erb.tt b/lib/generators/authentication/templates/erb/two_factor_authentication/profile/security_keys/index.html.erb.tt index f09d26c3..ac18d198 100644 --- a/lib/generators/authentication/templates/erb/two_factor_authentication/profile/security_keys/index.html.erb.tt +++ b/lib/generators/authentication/templates/erb/two_factor_authentication/profile/security_keys/index.html.erb.tt @@ -1,18 +1,18 @@

<%%= notice %>

-

Security keys

-

A security key is a hardware device used to verify your identity. For example, a built-in fingerprint reader, a plug-in USB key, or a login system like Windows Hello.

+

<%%= t('authentication_zero.two_factor_authentication.profile.security_keys.index.security_keys') %>

+

<%%= t('authentication_zero.two_factor_authentication.profile.security_keys.index.security_keys_description') %>

    <%%= render @security_keys %>

- <%%= link_to "Add security key", new_two_factor_authentication_profile_security_key_path %> + <%%= link_to t('authentication_zero.two_factor_authentication.profile.security_keys.index.add_security_key'), new_two_factor_authentication_profile_security_key_path %>

- <%%= link_to "Back", root_path %> + <%%= link_to t('authentication_zero.two_factor_authentication.profile.security_keys.index.back'), root_path %>
diff --git a/lib/generators/authentication/templates/erb/two_factor_authentication/profile/security_keys/new.html.erb.tt b/lib/generators/authentication/templates/erb/two_factor_authentication/profile/security_keys/new.html.erb.tt index 1078f7b0..ccbd2000 100644 --- a/lib/generators/authentication/templates/erb/two_factor_authentication/profile/security_keys/new.html.erb.tt +++ b/lib/generators/authentication/templates/erb/two_factor_authentication/profile/security_keys/new.html.erb.tt @@ -5,8 +5,8 @@ -

Add a security key

-

Have your security key ready. If it's the USB kind insert it now and then, if it has one, press the activation button when asked.

+

<%%= t('authentication_zero.two_factor_authentication.profile.security_keys.new.add_security_key') %>

+

<%%= t('authentication_zero.two_factor_authentication.profile.security_keys.new.ready_instructions') %>

- <%%= button_tag "I'm ready, let's go", type: :button, data: { web_authn_target: "button", action: "web-authn#createCredential" } %> + <%%= button_tag t('authentication_zero.two_factor_authentication.profile.security_keys.new.im_ready'), type: :button, data: { web_authn_target: "button", action: "web-authn#createCredential" } %> diff --git a/lib/generators/authentication/templates/erb/two_factor_authentication/profile/totps/new.html.erb.tt b/lib/generators/authentication/templates/erb/two_factor_authentication/profile/totps/new.html.erb.tt index 4c4e6254..fc17307f 100644 --- a/lib/generators/authentication/templates/erb/two_factor_authentication/profile/totps/new.html.erb.tt +++ b/lib/generators/authentication/templates/erb/two_factor_authentication/profile/totps/new.html.erb.tt @@ -1,44 +1,44 @@

<%%= alert %>

<%% if Current.user.otp_required_for_sign_in? %> -

Want to replace your existing 2FA setup?

+

<%%= t('authentication_zero.two_factor_authentication.profile.totps.new.replace_existing_2fa') %>

-

Your account is already protected with two-factor authentication. You can replace that setup if you want to switch to a new phone or authenticator app.

+

<%%= t('authentication_zero.two_factor_authentication.profile.totps.new.already_protected') %>

-

Do you want to continue? Your existing 2FA setup will no longer work.

+

<%%= t('authentication_zero.two_factor_authentication.profile.totps.new.continue_warning') %>

- <%%= button_to "Yes, replace my 2FA setup", two_factor_authentication_profile_totp_path, method: :patch %> + <%%= button_to t('authentication_zero.two_factor_authentication.profile.totps.new.yes_replace'), two_factor_authentication_profile_totp_path, method: :patch %>
<%% end %> -

Upgrade your security with 2FA

+

<%%= t('authentication_zero.two_factor_authentication.profile.totps.new.upgrade_security') %>

-

Step 1: Get an Authenticator App

-

First, you'll need a 2FA authenticator app on your phone. If you already have one, skip to step 2.

-

If you don't have one, or you aren't sure, we recommend Microsoft Authenticator. You can download it free on the Apple App Store for iPhone, or Google Play Store for Android. Please grab your phone, search the store, and install it now.

+

<%%= t('authentication_zero.two_factor_authentication.profile.totps.new.step1_get_app') %>

+

<%%= t('authentication_zero.two_factor_authentication.profile.totps.new.get_app_instructions') %>

+

<%%= t('authentication_zero.two_factor_authentication.profile.totps.new.recommend_app') %>

-

Step 2: Scan + Enter the Code

-

Next, open the authenticator app, tap "Scan QR code" or "+", and, when it asks, point your phone's camera at this QR code picture below.

+

<%%= t('authentication_zero.two_factor_authentication.profile.totps.new.step2_scan_enter') %>

+

<%%= t('authentication_zero.two_factor_authentication.profile.totps.new.scan_instructions') %>

<%%= image_tag @qr_code.as_png(resize_exactly_to: 200).to_data_url%> -
Point your camera here
+
<%%= t('authentication_zero.two_factor_authentication.profile.totps.new.point_camera') %>
<%%= form_with(url: two_factor_authentication_profile_totp_path) do |form| %>
- <%%= form.label :code, "After scanning with your camera, the app will generate a six-digit code. Enter it here:", style: "display: block" %> + <%%= form.label :code, t('authentication_zero.two_factor_authentication.profile.totps.new.enter_code_instructions'), style: "display: block" %> <%%= form.text_field :code, required: true, autofocus: true, autocomplete: :off %>
- <%%= form.submit "Verify and activate" %> + <%%= form.submit t('authentication_zero.two_factor_authentication.profile.totps.new.verify_activate') %>
<%% end %>
- <%%= link_to "Back", root_path %> + <%%= link_to t('authentication_zero.two_factor_authentication.profile.totps.new.back'), root_path %>
diff --git a/lib/generators/authentication/templates/erb/user_mailer/email_verification.html.erb.tt b/lib/generators/authentication/templates/erb/user_mailer/email_verification.html.erb.tt index 26e97dd5..9d8f13b8 100644 --- a/lib/generators/authentication/templates/erb/user_mailer/email_verification.html.erb.tt +++ b/lib/generators/authentication/templates/erb/user_mailer/email_verification.html.erb.tt @@ -1,11 +1,11 @@ -

Hey there,

+

<%%= t('authentication_zero.user_mailer.email_verification.greeting') %>

-

This is to confirm that <%%= @user.email %> is the email you want to use on your account. If you ever lose your password, that's where we'll email a reset link.

+

<%%= t('authentication_zero.user_mailer.email_verification.confirmation_text', email: @user.email) %>

-

You must hit the link below to confirm that you received this email.

+

<%%= t('authentication_zero.user_mailer.email_verification.must_confirm') %>

-

<%%= link_to "Yes, use this email for my account", identity_email_verification_url(sid: @signed_id) %>

+

<%%= link_to t('authentication_zero.user_mailer.email_verification.confirm_link'), identity_email_verification_url(sid: @signed_id) %>


-

Have questions or need help? Just reply to this email and our support team will help you sort it out.

+

<%%= t('authentication_zero.user_mailer.email_verification.help_text') %>

diff --git a/lib/generators/authentication/templates/erb/user_mailer/invitation_instructions.html.erb.tt b/lib/generators/authentication/templates/erb/user_mailer/invitation_instructions.html.erb.tt index d4330c75..7e291dd2 100644 --- a/lib/generators/authentication/templates/erb/user_mailer/invitation_instructions.html.erb.tt +++ b/lib/generators/authentication/templates/erb/user_mailer/invitation_instructions.html.erb.tt @@ -1,11 +1,11 @@ -

Hey there,

+

<%%= t('authentication_zero.user_mailer.invitation_instructions.greeting') %>

-

Someone has invited you to the application, you can accept it through the link below.

+

<%%= t('authentication_zero.user_mailer.invitation_instructions.invitation_text') %>

-

<%%= link_to "Accept invitation", edit_identity_password_reset_url(sid: @signed_id) %>

+

<%%= link_to t('authentication_zero.user_mailer.invitation_instructions.accept_invitation'), edit_identity_password_reset_url(sid: @signed_id) %>

-

If you don't want to accept the invitation, please ignore this email. Your account won't be created until you access the link above and set your password.

+

<%%= t('authentication_zero.user_mailer.invitation_instructions.ignore_text') %>


-

Have questions or need help? Just reply to this email and our support team will help you sort it out.

+

<%%= t('authentication_zero.user_mailer.invitation_instructions.help_text') %>

diff --git a/lib/generators/authentication/templates/erb/user_mailer/password_reset.html.erb.tt b/lib/generators/authentication/templates/erb/user_mailer/password_reset.html.erb.tt index fbaaef28..acb887c1 100644 --- a/lib/generators/authentication/templates/erb/user_mailer/password_reset.html.erb.tt +++ b/lib/generators/authentication/templates/erb/user_mailer/password_reset.html.erb.tt @@ -1,11 +1,11 @@ -

Hey there,

+

<%%= t('authentication_zero.user_mailer.password_reset.greeting') %>

-

Can't remember your password for <%%= @user.email %>? That's OK, it happens. Just hit the link below to set a new one.

+

<%%= t('authentication_zero.user_mailer.password_reset.reset_text', email: @user.email) %>

-

<%%= link_to "Reset my password", edit_identity_password_reset_url(sid: @signed_id) %>

+

<%%= link_to t('authentication_zero.user_mailer.password_reset.reset_link'), edit_identity_password_reset_url(sid: @signed_id) %>

-

If you did not request a password reset you can safely ignore this email, it expires in 20 minutes. Only someone with access to this email account can reset your password.

+

<%%= t('authentication_zero.user_mailer.password_reset.ignore_text') %>


-

Have questions or need help? Just reply to this email and our support team will help you sort it out.

+

<%%= t('authentication_zero.user_mailer.password_reset.help_text') %>

diff --git a/lib/generators/authentication/templates/erb/user_mailer/passwordless.html.erb.tt b/lib/generators/authentication/templates/erb/user_mailer/passwordless.html.erb.tt index 716f8842..3f65a335 100644 --- a/lib/generators/authentication/templates/erb/user_mailer/passwordless.html.erb.tt +++ b/lib/generators/authentication/templates/erb/user_mailer/passwordless.html.erb.tt @@ -1,9 +1,9 @@ -

Hey there,

+

<%%= t('authentication_zero.user_mailer.passwordless.greeting') %>

-

You requested a magic sign-in link. Here you go:

+

<%%= t('authentication_zero.user_mailer.passwordless.magic_link_text') %>

-

<%%= link_to "Sign in without password", edit_sessions_passwordless_url(sid: @signed_id) %>

+

<%%= link_to t('authentication_zero.user_mailer.passwordless.sign_in_link'), edit_sessions_passwordless_url(sid: @signed_id) %>


-

Have questions or need help? Just reply to this email and our support team will help you sort it out.

+

<%%= t('authentication_zero.user_mailer.passwordless.help_text') %>

From c3637f0d74cf347135a6d1987e67d1188337aba8 Mon Sep 17 00:00:00 2001 From: Benedikt Laube Date: Tue, 21 Oct 2025 10:51:46 +0200 Subject: [PATCH 05/13] Use i18n decorators in mailer templates --- lib/authentication_zero/locales/en.yml | 5 +++++ .../authentication/templates/mailers/user_mailer.rb.tt | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/authentication_zero/locales/en.yml b/lib/authentication_zero/locales/en.yml index 64020f45..ee301a9e 100644 --- a/lib/authentication_zero/locales/en.yml +++ b/lib/authentication_zero/locales/en.yml @@ -157,6 +157,11 @@ en: verify_activate: "Verify and activate" back: "Back" user_mailer: + subjects: + password_reset: "Reset your password" + email_verification: "Verify your email" + passwordless: "Your sign in link" + invitation_instructions: "Invitation instructions" email_verification: greeting: "Hey there," confirmation_text: "This is to confirm that %{email} is the email you want to use on your account. If you ever lose your password, that's where we'll email a reset link." diff --git a/lib/generators/authentication/templates/mailers/user_mailer.rb.tt b/lib/generators/authentication/templates/mailers/user_mailer.rb.tt index 54fcc29e..c29aec01 100644 --- a/lib/generators/authentication/templates/mailers/user_mailer.rb.tt +++ b/lib/generators/authentication/templates/mailers/user_mailer.rb.tt @@ -3,21 +3,21 @@ class UserMailer < ApplicationMailer @user = params[:user] @signed_id = @user.generate_token_for(:password_reset) - mail to: @user.email, subject: "Reset your password" + mail to: @user.email, subject: t('authentication_zero.user_mailer.subjects.password_reset') end def email_verification @user = params[:user] @signed_id = @user.generate_token_for(:email_verification) - mail to: @user.email, subject: "Verify your email" + mail to: @user.email, subject: t('authentication_zero.user_mailer.subjects.email_verification') end <%- if passwordless? %> def passwordless @user = params[:user] @signed_id = @user.sign_in_tokens.create.signed_id(expires_in: 1.day) - mail to: @user.email, subject: "Your sign in link" + mail to: @user.email, subject: t('authentication_zero.user_mailer.subjects.passwordless') end <%- end -%> <%- if invitable? %> @@ -25,7 +25,7 @@ class UserMailer < ApplicationMailer @user = params[:user] @signed_id = @user.generate_token_for(:password_reset) - mail to: @user.email, subject: "Invitation instructions" + mail to: @user.email, subject: t('authentication_zero.user_mailer.subjects.invitation_instructions') end <%- end -%> end From a9e1d8b745c4687159136fd04cf763ffd53df1e4 Mon Sep 17 00:00:00 2001 From: Benedikt Laube Date: Tue, 21 Oct 2025 11:39:30 +0200 Subject: [PATCH 06/13] Use i18n decorators in controller templates --- lib/authentication_zero/locales/en.yml | 80 +++++++++++++++++++ .../email_verifications_controller.rb.tt | 2 +- .../identity/password_resets_controller.rb.tt | 4 +- .../controllers/api/sessions_controller.rb.tt | 2 +- .../email_verifications_controller.rb.tt | 6 +- .../html/identity/emails_controller.rb.tt | 2 +- .../identity/password_resets_controller.rb.tt | 8 +- .../html/invitations_controller.rb.tt | 2 +- .../html/masquerades_controller.rb.tt | 4 +- .../html/passwords_controller.rb.tt | 2 +- .../html/registrations_controller.rb.tt | 2 +- .../html/sessions/omniauth_controller.rb.tt | 4 +- .../sessions/passwordlesses_controller.rb.tt | 8 +- .../html/sessions/sudos_controller.rb.tt | 2 +- .../html/sessions_controller.rb.tt | 6 +- .../challenge/recovery_codes_controller.rb.tt | 4 +- .../challenge/security_keys_controller.rb.tt | 4 +- .../challenge/totps_controller.rb.tt | 4 +- .../profile/recovery_codes_controller.rb.tt | 2 +- .../profile/security_keys_controller.rb.tt | 4 +- .../profile/totps_controller.rb.tt | 2 +- 21 files changed, 117 insertions(+), 37 deletions(-) diff --git a/lib/authentication_zero/locales/en.yml b/lib/authentication_zero/locales/en.yml index ee301a9e..c411eb2a 100644 --- a/lib/authentication_zero/locales/en.yml +++ b/lib/authentication_zero/locales/en.yml @@ -156,6 +156,86 @@ en: enter_code_instructions: "After scanning with your camera, the app will generate a six-digit code. Enter it here:" verify_activate: "Verify and activate" back: "Back" + controllers: + invitations: + create: + invitation_sent: "An invitation email has been sent to %{email}" + masquerades: + create: + signed_in_successfully: "Signed in successfully" + authorize: + must_be_in_development: "You must be in development" + passwords: + update: + password_changed: "Your password has been changed" + registrations: + create: + welcome_signed_up: "Welcome! You have signed up successfully" + sessions: + create: + signed_in_successfully: "Signed in successfully" + incorrect_email_or_password: "That email or password is incorrect" + destroy: + session_logged_out: "That session has been logged out" + identity: + email_verifications: + show: + thank_you_verified: "Thank you for verifying your email address" + create: + verification_email_sent: "We sent a verification email to your email address" + emails: + update: + email_changed: "Your email has been changed" + password_resets: + create: + check_email_reset_instructions: "Check your email for reset instructions" + cant_reset_until_verified: "You can't reset your password until you verify your email" + update: + password_reset_success: "Your password was reset successfully. Please sign in" + set_user: + invalid_reset_link: "That password reset link is invalid" + sessions: + omniauth: + create: + signed_in_successfully: "Signed in successfully" + authentication_failed: "Authentication failed" + passwordlesses: + edit: + signed_in_successfully: "Signed in successfully" + create: + check_email_sign_in_instructions: "Check your email for sign in instructions" + cant_sign_in_until_verified: "You can't sign in until you verify your email" + set_user: + invalid_sign_in_link: "That sign in link is invalid" + sudos: + create: + incorrect_password: "The password you entered is incorrect" + two_factor_authentication: + challenge: + recovery_codes: + create: + code_didnt_work: "That code didn't work. Please try again" + set_user: + taking_too_long: "That's taking too long. Please re-enter your password and try again" + security_keys: + create: + verification_failed: "Verification failed: %{error}" + set_user: + taking_too_long: "That's taking too long. Please re-enter your password and try again" + totps: + create: + code_didnt_work: "That code didn't work. Please try again" + set_user: + taking_too_long: "That's taking too long. Please re-enter your password and try again" + profile: + recovery_codes: + create: + new_codes_generated: "Your new recovery codes have been generated" + security_keys: + update: + changes_saved: "Your changes have been saved" + destroy: + security_key_removed: "%{name} has been removed" user_mailer: subjects: password_reset: "Reset your password" diff --git a/lib/generators/authentication/templates/controllers/api/identity/email_verifications_controller.rb.tt b/lib/generators/authentication/templates/controllers/api/identity/email_verifications_controller.rb.tt index d1bf37ca..9e092826 100644 --- a/lib/generators/authentication/templates/controllers/api/identity/email_verifications_controller.rb.tt +++ b/lib/generators/authentication/templates/controllers/api/identity/email_verifications_controller.rb.tt @@ -15,6 +15,6 @@ class Identity::EmailVerificationsController < ApplicationController def set_user @user = User.find_by_token_for!(:email_verification, params[:sid]) rescue StandardError - render json: { error: "That email verification link is invalid" }, status: :bad_request + render json: { error: t('authentication_zero.controllers.identity.email_verifications.set_user.invalid_verification_link') }, status: :bad_request end end diff --git a/lib/generators/authentication/templates/controllers/api/identity/password_resets_controller.rb.tt b/lib/generators/authentication/templates/controllers/api/identity/password_resets_controller.rb.tt index 0cac5867..a4373a4d 100644 --- a/lib/generators/authentication/templates/controllers/api/identity/password_resets_controller.rb.tt +++ b/lib/generators/authentication/templates/controllers/api/identity/password_resets_controller.rb.tt @@ -11,7 +11,7 @@ class Identity::PasswordResetsController < ApplicationController if @user = User.find_by(email: params[:email], verified: true) UserMailer.with(user: @user).password_reset.deliver_later else - render json: { error: "You can't reset your password until you verify your email" }, status: :bad_request + render json: { error: t('authentication_zero.controllers.identity.password_resets.create.cant_reset_until_verified') }, status: :bad_request end end @@ -27,7 +27,7 @@ class Identity::PasswordResetsController < ApplicationController def set_user @user = User.find_by_token_for!(:password_reset, params[:sid]) rescue StandardError - render json: { error: "That password reset link is invalid" }, status: :bad_request + render json: { error: t('authentication_zero.controllers.identity.password_resets.set_user.invalid_reset_link') }, status: :bad_request end def user_params diff --git a/lib/generators/authentication/templates/controllers/api/sessions_controller.rb.tt b/lib/generators/authentication/templates/controllers/api/sessions_controller.rb.tt index 0d1f6ce1..38be94cc 100644 --- a/lib/generators/authentication/templates/controllers/api/sessions_controller.rb.tt +++ b/lib/generators/authentication/templates/controllers/api/sessions_controller.rb.tt @@ -18,7 +18,7 @@ class SessionsController < ApplicationController render json: @session, status: :created else - render json: { error: "That email or password is incorrect" }, status: :unauthorized + render json: { error: t('authentication_zero.controllers.sessions.create.incorrect_email_or_password') }, status: :unauthorized end end diff --git a/lib/generators/authentication/templates/controllers/html/identity/email_verifications_controller.rb.tt b/lib/generators/authentication/templates/controllers/html/identity/email_verifications_controller.rb.tt index 5c48dc10..31286b67 100644 --- a/lib/generators/authentication/templates/controllers/html/identity/email_verifications_controller.rb.tt +++ b/lib/generators/authentication/templates/controllers/html/identity/email_verifications_controller.rb.tt @@ -5,19 +5,19 @@ class Identity::EmailVerificationsController < ApplicationController def show @user.update! verified: true - redirect_to root_path, notice: "Thank you for verifying your email address" + redirect_to root_path, notice: t('authentication_zero.controllers.identity.email_verifications.show.thank_you_verified') end def create send_email_verification - redirect_to root_path, notice: "We sent a verification email to your email address" + redirect_to root_path, notice: t('authentication_zero.controllers.identity.email_verifications.create.verification_email_sent') end private def set_user @user = User.find_by_token_for!(:email_verification, params[:sid]) rescue StandardError - redirect_to edit_identity_email_path, alert: "That email verification link is invalid" + redirect_to edit_identity_email_path, alert: t('authentication_zero.controllers.identity.email_verifications.set_user.invalid_verification_link') end def send_email_verification diff --git a/lib/generators/authentication/templates/controllers/html/identity/emails_controller.rb.tt b/lib/generators/authentication/templates/controllers/html/identity/emails_controller.rb.tt index 407e3888..01112902 100644 --- a/lib/generators/authentication/templates/controllers/html/identity/emails_controller.rb.tt +++ b/lib/generators/authentication/templates/controllers/html/identity/emails_controller.rb.tt @@ -24,7 +24,7 @@ class Identity::EmailsController < ApplicationController def redirect_to_root if @user.email_previously_changed? resend_email_verification - redirect_to root_path, notice: "Your email has been changed" + redirect_to root_path, notice: t('authentication_zero.controllers.identity.emails.update.email_changed') else redirect_to root_path end diff --git a/lib/generators/authentication/templates/controllers/html/identity/password_resets_controller.rb.tt b/lib/generators/authentication/templates/controllers/html/identity/password_resets_controller.rb.tt index e452e0a5..95610bcb 100644 --- a/lib/generators/authentication/templates/controllers/html/identity/password_resets_controller.rb.tt +++ b/lib/generators/authentication/templates/controllers/html/identity/password_resets_controller.rb.tt @@ -15,15 +15,15 @@ class Identity::PasswordResetsController < ApplicationController def create if @user = User.find_by(email: params[:email], verified: true) send_password_reset_email - redirect_to sign_in_path, notice: "Check your email for reset instructions" + redirect_to sign_in_path, notice: t('authentication_zero.controllers.identity.password_resets.create.check_email_reset_instructions') else - redirect_to new_identity_password_reset_path, alert: "You can't reset your password until you verify your email" + redirect_to new_identity_password_reset_path, alert: t('authentication_zero.controllers.identity.password_resets.create.cant_reset_until_verified') end end def update if @user.update(user_params) - redirect_to sign_in_path, notice: "Your password was reset successfully. Please sign in" + redirect_to sign_in_path, notice: t('authentication_zero.controllers.identity.password_resets.update.password_reset_success') else render :edit, status: :unprocessable_entity end @@ -33,7 +33,7 @@ class Identity::PasswordResetsController < ApplicationController def set_user @user = User.find_by_token_for!(:password_reset, params[:sid]) rescue StandardError - redirect_to new_identity_password_reset_path, alert: "That password reset link is invalid" + redirect_to new_identity_password_reset_path, alert: t('authentication_zero.controllers.identity.password_resets.set_user.invalid_reset_link') end def user_params diff --git a/lib/generators/authentication/templates/controllers/html/invitations_controller.rb.tt b/lib/generators/authentication/templates/controllers/html/invitations_controller.rb.tt index 1b4a28a4..23e2100d 100644 --- a/lib/generators/authentication/templates/controllers/html/invitations_controller.rb.tt +++ b/lib/generators/authentication/templates/controllers/html/invitations_controller.rb.tt @@ -8,7 +8,7 @@ class InvitationsController < ApplicationController if @user.save send_invitation_instructions - redirect_to new_invitation_path, notice: "An invitation email has been sent to #{@user.email}" + redirect_to new_invitation_path, notice: t('authentication_zero.controllers.invitations.create.invitation_sent', email: @user.email) else render :new, status: :unprocessable_entity end diff --git a/lib/generators/authentication/templates/controllers/html/masquerades_controller.rb.tt b/lib/generators/authentication/templates/controllers/html/masquerades_controller.rb.tt index e2a6994b..89975141 100644 --- a/lib/generators/authentication/templates/controllers/html/masquerades_controller.rb.tt +++ b/lib/generators/authentication/templates/controllers/html/masquerades_controller.rb.tt @@ -6,7 +6,7 @@ class MasqueradesController < ApplicationController session_record = @user.sessions.create! cookies.signed.permanent[:session_token] = { value: session_record.id, httponly: true } - redirect_to root_path, notice: "Signed in successfully" + redirect_to root_path, notice: t('authentication_zero.controllers.masquerades.create.signed_in_successfully') end private @@ -15,6 +15,6 @@ class MasqueradesController < ApplicationController end def authorize - redirect_to(root_path, alert: "You must be in development") unless Rails.env.development? + redirect_to(root_path, alert: t('authentication_zero.controllers.masquerades.authorize.must_be_in_development')) unless Rails.env.development? end end diff --git a/lib/generators/authentication/templates/controllers/html/passwords_controller.rb.tt b/lib/generators/authentication/templates/controllers/html/passwords_controller.rb.tt index 1956a8bc..d4d06dbe 100644 --- a/lib/generators/authentication/templates/controllers/html/passwords_controller.rb.tt +++ b/lib/generators/authentication/templates/controllers/html/passwords_controller.rb.tt @@ -6,7 +6,7 @@ class PasswordsController < ApplicationController def update if @user.update(user_params) - redirect_to root_path, notice: "Your password has been changed" + redirect_to root_path, notice: t('authentication_zero.controllers.passwords.update.password_changed') else render :edit, status: :unprocessable_entity end diff --git a/lib/generators/authentication/templates/controllers/html/registrations_controller.rb.tt b/lib/generators/authentication/templates/controllers/html/registrations_controller.rb.tt index 11267616..fc46c083 100644 --- a/lib/generators/authentication/templates/controllers/html/registrations_controller.rb.tt +++ b/lib/generators/authentication/templates/controllers/html/registrations_controller.rb.tt @@ -13,7 +13,7 @@ class RegistrationsController < ApplicationController cookies.signed.permanent[:session_token] = { value: session_record.id, httponly: true } send_email_verification - redirect_to root_path, notice: "Welcome! You have signed up successfully" + redirect_to root_path, notice: t('authentication_zero.controllers.registrations.create.welcome_signed_up') else render :new, status: :unprocessable_entity end diff --git a/lib/generators/authentication/templates/controllers/html/sessions/omniauth_controller.rb.tt b/lib/generators/authentication/templates/controllers/html/sessions/omniauth_controller.rb.tt index eda4fdc8..95c4080a 100644 --- a/lib/generators/authentication/templates/controllers/html/sessions/omniauth_controller.rb.tt +++ b/lib/generators/authentication/templates/controllers/html/sessions/omniauth_controller.rb.tt @@ -9,9 +9,9 @@ class Sessions::OmniauthController < ApplicationController session_record = @user.sessions.create! cookies.signed.permanent[:session_token] = { value: session_record.id, httponly: true } - redirect_to root_path, notice: "Signed in successfully" + redirect_to root_path, notice: t('authentication_zero.controllers.sessions.omniauth.create.signed_in_successfully') else - redirect_to sign_in_path, alert: "Authentication failed" + redirect_to sign_in_path, alert: t('authentication_zero.controllers.sessions.omniauth.create.authentication_failed') end end diff --git a/lib/generators/authentication/templates/controllers/html/sessions/passwordlesses_controller.rb.tt b/lib/generators/authentication/templates/controllers/html/sessions/passwordlesses_controller.rb.tt index 4ac6a60a..66f362ff 100644 --- a/lib/generators/authentication/templates/controllers/html/sessions/passwordlesses_controller.rb.tt +++ b/lib/generators/authentication/templates/controllers/html/sessions/passwordlesses_controller.rb.tt @@ -14,15 +14,15 @@ class Sessions::PasswordlessesController < ApplicationController cookies.signed.permanent[:session_token] = { value: session_record.id, httponly: true } revoke_sign_in_tokens - redirect_to(root_path, notice: "Signed in successfully") + redirect_to(root_path, notice: t('authentication_zero.controllers.sessions.passwordlesses.edit.signed_in_successfully')) end def create if @user = User.find_by(email: params[:email], verified: true) send_passwordless_email - redirect_to sign_in_path, notice: "Check your email for sign in instructions" + redirect_to sign_in_path, notice: t('authentication_zero.controllers.sessions.passwordlesses.create.check_email_sign_in_instructions') else - redirect_to new_sessions_passwordless_path, alert: "You can't sign in until you verify your email" + redirect_to new_sessions_passwordless_path, alert: t('authentication_zero.controllers.sessions.passwordlesses.create.cant_sign_in_until_verified') end end @@ -30,7 +30,7 @@ class Sessions::PasswordlessesController < ApplicationController def set_user token = SignInToken.find_signed!(params[:sid]); @user = token.user rescue StandardError - redirect_to new_sessions_passwordless_path, alert: "That sign in link is invalid" + redirect_to new_sessions_passwordless_path, alert: t('authentication_zero.controllers.sessions.passwordlesses.set_user.invalid_sign_in_link') end def send_passwordless_email diff --git a/lib/generators/authentication/templates/controllers/html/sessions/sudos_controller.rb.tt b/lib/generators/authentication/templates/controllers/html/sessions/sudos_controller.rb.tt index ed235e6a..7cce41d6 100644 --- a/lib/generators/authentication/templates/controllers/html/sessions/sudos_controller.rb.tt +++ b/lib/generators/authentication/templates/controllers/html/sessions/sudos_controller.rb.tt @@ -8,7 +8,7 @@ class Sessions::SudosController < ApplicationController if session_record.user.authenticate(params[:password]) session_record.touch(:sudo_at); redirect_to(params[:proceed_to_url]) else - redirect_to new_sessions_sudo_path(proceed_to_url: params[:proceed_to_url]), alert: "The password you entered is incorrect" + redirect_to new_sessions_sudo_path(proceed_to_url: params[:proceed_to_url]), alert: t('authentication_zero.controllers.sessions.sudos.create.incorrect_password') end end end diff --git a/lib/generators/authentication/templates/controllers/html/sessions_controller.rb.tt b/lib/generators/authentication/templates/controllers/html/sessions_controller.rb.tt index 09c02e28..a76ef494 100644 --- a/lib/generators/authentication/templates/controllers/html/sessions_controller.rb.tt +++ b/lib/generators/authentication/templates/controllers/html/sessions_controller.rb.tt @@ -20,7 +20,7 @@ class SessionsController < ApplicationController @session = user.sessions.create! cookies.signed.permanent[:session_token] = { value: @session.id, httponly: true } - redirect_to root_path, notice: "Signed in successfully" + redirect_to root_path, notice: t('authentication_zero.controllers.sessions.create.signed_in_successfully') end <%- else -%> @session = user.sessions.create! @@ -29,12 +29,12 @@ class SessionsController < ApplicationController redirect_to root_path, notice: "Signed in successfully" <%- end -%> else - redirect_to sign_in_path(email_hint: params[:email]), alert: "That email or password is incorrect" + redirect_to sign_in_path(email_hint: params[:email]), alert: t('authentication_zero.controllers.sessions.create.incorrect_email_or_password') end end def destroy - @session.destroy; redirect_to(sessions_path, notice: "That session has been logged out") + @session.destroy; redirect_to(sessions_path, notice: t('authentication_zero.controllers.sessions.destroy.session_logged_out')) end private diff --git a/lib/generators/authentication/templates/controllers/html/two_factor_authentication/challenge/recovery_codes_controller.rb.tt b/lib/generators/authentication/templates/controllers/html/two_factor_authentication/challenge/recovery_codes_controller.rb.tt index 7a62a8a1..1fea8811 100644 --- a/lib/generators/authentication/templates/controllers/html/two_factor_authentication/challenge/recovery_codes_controller.rb.tt +++ b/lib/generators/authentication/templates/controllers/html/two_factor_authentication/challenge/recovery_codes_controller.rb.tt @@ -10,7 +10,7 @@ class TwoFactorAuthentication::Challenge::RecoveryCodesController < ApplicationC if recover_code = @user.recovery_codes.find_by(code: params[:code], used: false) recover_code.update!(used: true); sign_in_and_redirect_to_root else - redirect_to new_two_factor_authentication_challenge_recovery_codes_path, alert: "That code didn't work. Please try again" + redirect_to new_two_factor_authentication_challenge_recovery_codes_path, alert: t('authentication_zero.controllers.two_factor_authentication.challenge.recovery_codes.create.code_didnt_work') end end @@ -18,7 +18,7 @@ class TwoFactorAuthentication::Challenge::RecoveryCodesController < ApplicationC def set_user @user = User.find_signed!(session[:challenge_token], purpose: :authentication_challenge) rescue StandardError - redirect_to sign_in_path, alert: "That's taking too long. Please re-enter your password and try again" + redirect_to sign_in_path, alert: t('authentication_zero.controllers.two_factor_authentication.challenge.recovery_codes.set_user.taking_too_long') end def sign_in_and_redirect_to_root diff --git a/lib/generators/authentication/templates/controllers/html/two_factor_authentication/challenge/security_keys_controller.rb.tt b/lib/generators/authentication/templates/controllers/html/two_factor_authentication/challenge/security_keys_controller.rb.tt index 1b386608..a4b2b3da 100644 --- a/lib/generators/authentication/templates/controllers/html/two_factor_authentication/challenge/security_keys_controller.rb.tt +++ b/lib/generators/authentication/templates/controllers/html/two_factor_authentication/challenge/security_keys_controller.rb.tt @@ -14,7 +14,7 @@ class TwoFactorAuthentication::Challenge::SecurityKeysController < ApplicationCo if @user.security_keys.exists?(external_id: credential.id) sign_in_and_redirect_to_root else - render json: { error: "Verification failed: #{e.message}" }, status: :unprocessable_entity + render json: { error: t('authentication_zero.controllers.two_factor_authentication.challenge.security_keys.create.verification_failed', error: e.message) }, status: :unprocessable_entity end end @@ -22,7 +22,7 @@ class TwoFactorAuthentication::Challenge::SecurityKeysController < ApplicationCo def set_user @user = User.find_signed!(session[:challenge_token], purpose: :authentication_challenge) rescue StandardError - redirect_to sign_in_path, alert: "That's taking too long. Please re-enter your password and try again" + redirect_to sign_in_path, alert: t('authentication_zero.controllers.two_factor_authentication.challenge.security_keys.set_user.taking_too_long') end def sign_in_and_redirect_to_root diff --git a/lib/generators/authentication/templates/controllers/html/two_factor_authentication/challenge/totps_controller.rb.tt b/lib/generators/authentication/templates/controllers/html/two_factor_authentication/challenge/totps_controller.rb.tt index 33879d2c..b9bf1c41 100644 --- a/lib/generators/authentication/templates/controllers/html/two_factor_authentication/challenge/totps_controller.rb.tt +++ b/lib/generators/authentication/templates/controllers/html/two_factor_authentication/challenge/totps_controller.rb.tt @@ -12,7 +12,7 @@ class TwoFactorAuthentication::Challenge::TotpsController < ApplicationControlle if @totp.verify(params[:code], drift_behind: 15) sign_in_and_redirect_to_root else - redirect_to new_two_factor_authentication_challenge_totp_path, alert: "That code didn't work. Please try again" + redirect_to new_two_factor_authentication_challenge_totp_path, alert: t('authentication_zero.controllers.two_factor_authentication.challenge.totps.create.code_didnt_work') end end @@ -20,7 +20,7 @@ class TwoFactorAuthentication::Challenge::TotpsController < ApplicationControlle def set_user @user = User.find_signed!(session[:challenge_token], purpose: :authentication_challenge) rescue StandardError - redirect_to sign_in_path, alert: "That's taking too long. Please re-enter your password and try again" + redirect_to sign_in_path, alert: t('authentication_zero.controllers.two_factor_authentication.challenge.totps.set_user.taking_too_long') end def sign_in_and_redirect_to_root diff --git a/lib/generators/authentication/templates/controllers/html/two_factor_authentication/profile/recovery_codes_controller.rb.tt b/lib/generators/authentication/templates/controllers/html/two_factor_authentication/profile/recovery_codes_controller.rb.tt index 04ae2224..f6f43255 100644 --- a/lib/generators/authentication/templates/controllers/html/two_factor_authentication/profile/recovery_codes_controller.rb.tt +++ b/lib/generators/authentication/templates/controllers/html/two_factor_authentication/profile/recovery_codes_controller.rb.tt @@ -13,7 +13,7 @@ class TwoFactorAuthentication::Profile::RecoveryCodesController < ApplicationCon @user.recovery_codes.delete_all @user.recovery_codes.create!(new_recovery_codes) - redirect_to two_factor_authentication_profile_recovery_codes_path, notice: "Your new recovery codes have been generated" + redirect_to two_factor_authentication_profile_recovery_codes_path, notice: t('authentication_zero.controllers.two_factor_authentication.profile.recovery_codes.create.new_codes_generated') end private diff --git a/lib/generators/authentication/templates/controllers/html/two_factor_authentication/profile/security_keys_controller.rb.tt b/lib/generators/authentication/templates/controllers/html/two_factor_authentication/profile/security_keys_controller.rb.tt index 8c4fa58a..0d6e3829 100644 --- a/lib/generators/authentication/templates/controllers/html/two_factor_authentication/profile/security_keys_controller.rb.tt +++ b/lib/generators/authentication/templates/controllers/html/two_factor_authentication/profile/security_keys_controller.rb.tt @@ -23,12 +23,12 @@ class TwoFactorAuthentication::Profile::SecurityKeysController < ApplicationCont def update @security_key.update! name: params[:name] - redirect_to two_factor_authentication_profile_security_keys_path, notice: "Your changes have been saved" + redirect_to two_factor_authentication_profile_security_keys_path, notice: t('authentication_zero.controllers.two_factor_authentication.profile.security_keys.update.changes_saved') end def destroy @security_key.destroy - redirect_to two_factor_authentication_profile_security_keys_path, notice: "#{@security_key.name} has been removed" + redirect_to two_factor_authentication_profile_security_keys_path, notice: t('authentication_zero.controllers.two_factor_authentication.profile.security_keys.destroy.security_key_removed', name: @security_key.name) end private diff --git a/lib/generators/authentication/templates/controllers/html/two_factor_authentication/profile/totps_controller.rb.tt b/lib/generators/authentication/templates/controllers/html/two_factor_authentication/profile/totps_controller.rb.tt index 8e74ab11..34667f70 100644 --- a/lib/generators/authentication/templates/controllers/html/two_factor_authentication/profile/totps_controller.rb.tt +++ b/lib/generators/authentication/templates/controllers/html/two_factor_authentication/profile/totps_controller.rb.tt @@ -11,7 +11,7 @@ class TwoFactorAuthentication::Profile::TotpsController < ApplicationController @user.update! otp_required_for_sign_in: true redirect_to two_factor_authentication_profile_recovery_codes_path else - redirect_to new_two_factor_authentication_profile_totp_path, alert: "That code didn't work. Please try again" + redirect_to new_two_factor_authentication_profile_totp_path, alert: t('authentication_zero.controllers.two_factor_authentication.profile.totps.create.code_didnt_work') end end From efd257539b58a2905f114008743613d3a7637a81 Mon Sep 17 00:00:00 2001 From: Benedikt Laube Date: Tue, 21 Oct 2025 11:46:01 +0200 Subject: [PATCH 07/13] Add German and Japanese translations (using AI translation) --- lib/authentication_zero/locales/de.yml | 270 +++++++++++++++++++++++++ lib/authentication_zero/locales/ja.yml | 270 +++++++++++++++++++++++++ 2 files changed, 540 insertions(+) create mode 100644 lib/authentication_zero/locales/de.yml create mode 100644 lib/authentication_zero/locales/ja.yml diff --git a/lib/authentication_zero/locales/de.yml b/lib/authentication_zero/locales/de.yml new file mode 100644 index 00000000..24f55ff9 --- /dev/null +++ b/lib/authentication_zero/locales/de.yml @@ -0,0 +1,270 @@ +de: + authentication_zero: + home: + index: + signed_as: "Angemeldet als %{email}" + login_and_verification: "Anmeldung und Verifizierung" + change_password: "Passwort ändern" + change_email_address: "E-Mail-Adresse ändern" + two_factor_authentication: "Zwei-Faktor-Authentifizierung" + recovery_codes: "Wiederherstellungscodes" + security_keys: "Sicherheitsschlüssel" + send_invitation: "Einladung senden" + signin_as_last_user: "Als letzter Benutzer anmelden" + access_history: "Zugriffsverlauf" + devices_sessions: "Geräte & Sitzungen" + activity_log: "Aktivitätsprotokoll" + log_out: "Abmelden" + authentications: + events: + index: + activity_log: "Aktivitätsprotokoll" + user_agent: "User-Agent:" + action: "Aktion:" + ip_address: "IP-Adresse:" + created_at: "Erstellt am:" + back: "Zurück" + identity: + emails: + edit: + change_your_email: "Ihre E-Mail ändern" + verify_your_email: "Ihre E-Mail verifizieren" + verification_sent: "Wir haben eine Verifizierungs-E-Mail an die unten stehende Adresse gesendet. Überprüfen Sie diese E-Mail und folgen Sie den Anweisungen, um zu bestätigen, dass es Ihre E-Mail-Adresse ist." + re_send_verification_email: "Verifizierungs-E-Mail erneut senden" + new_email: "Neue E-Mail" + password_challenge: "Passwort-Herausforderung" + save_changes: "Änderungen speichern" + back: "Zurück" + password_resets: + edit: + reset_your_password: "Ihr Passwort zurücksetzen" + new_password: "Neues Passwort" + confirm_new_password: "Neues Passwort bestätigen" + password_minimum: "Mindestens 12 Zeichen." + save_changes: "Änderungen speichern" + new: + forgot_your_password: "Passwort vergessen?" + send_password_reset_email: "E-Mail zum Zurücksetzen des Passworts senden" + invitations: + new: + send_invitation: "Einladung senden" + send_an_invitation: "Eine Einladung senden" + back: "Zurück" + passwords: + edit: + change_your_password: "Ihr Passwort ändern" + new_password: "Neues Passwort" + confirm_new_password: "Neues Passwort bestätigen" + password_minimum: "Mindestens 12 Zeichen." + save_changes: "Änderungen speichern" + back: "Zurück" + registrations: + new: + sign_up: "Registrieren" + password_minimum: "Mindestens 12 Zeichen." + sessions: + index: + devices_sessions: "Geräte & Sitzungen" + user_agent: "User-Agent:" + ip_address: "IP-Adresse:" + created_at: "Erstellt am:" + log_out: "Abmelden" + back: "Zurück" + new: + sign_in: "Anmelden" + sign_in_without_password: "Ohne Passwort anmelden" + sign_in_with_omniauth: "Mit OmniAuth anmelden" + sign_up: "Registrieren" + forgot_your_password: "Passwort vergessen?" + passwordlesses: + new: + sign_in_without_password: "Ohne Passwort anmelden" + sign_in: "Anmelden" + sudos: + new: + enter_password_to_continue: "Geben Sie Ihr Passwort ein, um fortzufahren" + continue: "Fortfahren" + why_asking: "Warum fragen Sie mich danach?" + protection_explanation: "Um Ihr Konto besser zu schützen, bitten wir Sie gelegentlich, Ihr Passwort zu bestätigen, bevor Sie sensible Aktionen ausführen." + forgot_password: "Passwort vergessen?" + reset_help: "Wir helfen Ihnen dabei, %{link}, damit Sie fortfahren können." + reset_link_text: "es zurückzusetzen" + two_factor_authentication: + challenge: + recovery_codes: + new: + enter_recovery_code: "OK, geben Sie unten einen Ihrer Wiederherstellungscodes ein:" + continue: "Fortfahren" + access_instructions: "Um auf Ihr Konto zuzugreifen, geben Sie einen der Wiederherstellungscodes ein (z. B. xxxxxxxxxx), die Sie beim Einrichten Ihres Zwei-Faktor-Authentifizierungsgeräts gespeichert haben." + security_keys: + new: + verify_with_security_key: "Mit Ihrem Sicherheitsschlüssel verifizieren." + use_security_key: "Sicherheitsschlüssel verwenden" + security_key_instructions: "Halten Sie Ihren Sicherheitsschlüssel bereit. Wenn es sich um einen USB-Typ handelt, schließen Sie ihn jetzt an und drücken Sie die Aktivierungstaste, wenn Sie dazu aufgefordert werden." + totps: + new: + enter_2fa_code: "Öffnen Sie als Nächstes die 2FA-Authentifizierungs-App auf Ihrem Telefon und geben Sie den sechsstelligen Code unten ein:" + verify: "Verifizieren" + dont_have_phone: "Haben Sie Ihr Telefon nicht dabei?" + use_recovery_code: "Verwenden Sie einen Wiederherstellungscode, um auf Ihr Konto zuzugreifen." + use_security_key: "Verwenden Sie einen Sicherheitsschlüssel, um auf Ihr Konto zuzugreifen." + profile: + recovery_codes: + index: + two_factor_recovery_codes: "Zwei-Faktor-Wiederherstellungscodes" + recovery_codes_description: "Wiederherstellungscodes bieten eine Möglichkeit, sich anzumelden, wenn Sie Ihr Telefon verlieren (oder es nicht dabei haben). Speichern Sie diese und bewahren Sie sie an einem sicheren Ort auf." + ok_done: "OK, ich bin fertig" + need_new_codes: "Brauchen Sie neue Wiederherstellungscodes?" + new_codes_warning: "Wenn Sie glauben, dass Ihre Codes in die falschen Hände geraten sind, können Sie einen neuen Satz erhalten. Stellen Sie sicher, dass Sie die neuen speichern, da die alten Codes nicht mehr funktionieren werden." + generate_new_codes: "Neue Wiederherstellungscodes generieren" + security_keys: + _form_confirm: + one_more_step: "Ein weiterer Schritt. Bitte geben Sie diesem Sicherheitsschlüssel einen Spitznamen, damit Sie sich daran erinnern können." + name: "Name" + example: "z. B. Macbook Touch ID" + save: "Speichern" + _form_edit: + name: "Name" + example: "z. B. Macbook Touch ID" + save_changes: "Änderungen speichern" + remove_security_key: "Diesen Sicherheitsschlüssel entfernen..." + edit: + edit_security_key: "Sicherheitsschlüssel bearbeiten" + index: + security_keys: "Sicherheitsschlüssel" + security_keys_description: "Ein Sicherheitsschlüssel ist ein Hardwaregerät, das zur Verifizierung Ihrer Identität verwendet wird. Zum Beispiel ein eingebauter Fingerabdruckleser, ein anschließbarer USB-Schlüssel oder ein Anmeldesystem wie Windows Hello." + add_security_key: "Sicherheitsschlüssel hinzufügen" + back: "Zurück" + new: + add_security_key: "Einen Sicherheitsschlüssel hinzufügen" + ready_instructions: "Halten Sie Ihren Sicherheitsschlüssel bereit. Wenn es sich um einen USB-Typ handelt, schließen Sie ihn jetzt an und drücken Sie die Aktivierungstaste, wenn Sie dazu aufgefordert werden." + im_ready: "Ich bin bereit, los geht's" + totps: + new: + replace_existing_2fa: "Möchten Sie Ihre bestehende 2FA-Einrichtung ersetzen?" + already_protected: "Ihr Konto ist bereits mit Zwei-Faktor-Authentifizierung geschützt. Sie können diese Einrichtung ersetzen, wenn Sie zu einem neuen Telefon oder einer neuen Authentifizierungs-App wechseln möchten." + continue_warning: "Möchten Sie fortfahren? Ihre bestehende 2FA-Einrichtung wird nicht mehr funktionieren." + yes_replace: "Ja, meine 2FA-Einrichtung ersetzen" + upgrade_security: "Verbessern Sie Ihre Sicherheit mit 2FA" + step1_get_app: "Schritt 1: Eine Authentifizierungs-App herunterladen" + get_app_instructions: "Zuerst benötigen Sie eine 2FA-Authentifizierungs-App auf Ihrem Telefon. %{strong_text}" + skip_if_have: "Wenn Sie bereits eine haben, überspringen Sie Schritt 2." + recommend_app: "Wenn Sie keine haben oder unsicher sind, empfehlen wir Microsoft Authenticator. Sie können es kostenlos im Apple App Store für iPhone oder Google Play Store für Android herunterladen. Bitte nehmen Sie Ihr Telefon, suchen Sie im Store und installieren Sie es jetzt." + step2_scan_enter: "Schritt 2: Scannen + Code eingeben" + scan_instructions: "Öffnen Sie als Nächstes die Authentifizierungs-App, tippen Sie auf \"QR-Code scannen\" oder \"+\", und wenn Sie dazu aufgefordert werden, richten Sie die Kamera Ihres Telefons auf das QR-Code-Bild unten." + point_camera: "Richten Sie Ihre Kamera hierher" + enter_code_instructions: "Nach dem Scannen mit Ihrer Kamera generiert die App einen sechsstelligen Code. Geben Sie ihn hier ein:" + verify_activate: "Verifizieren und aktivieren" + back: "Zurück" + controllers: + invitations: + create: + invitation_sent: "Eine Einladungs-E-Mail wurde an %{email} gesendet" + masquerades: + create: + signed_in_successfully: "Erfolgreich angemeldet" + authorize: + must_be_in_development: "Sie müssen sich in der Entwicklungsumgebung befinden" + passwords: + update: + password_changed: "Ihr Passwort wurde geändert" + registrations: + create: + welcome_signed_up: "Willkommen! Sie haben sich erfolgreich registriert" + sessions: + create: + signed_in_successfully: "Erfolgreich angemeldet" + incorrect_email_or_password: "Diese E-Mail oder dieses Passwort ist falsch" + destroy: + session_logged_out: "Diese Sitzung wurde beendet" + identity: + email_verifications: + show: + thank_you_verified: "Vielen Dank für die Verifizierung Ihrer E-Mail-Adresse" + create: + verification_email_sent: "Wir haben eine Verifizierungs-E-Mail an Ihre E-Mail-Adresse gesendet" + emails: + update: + email_changed: "Ihre E-Mail wurde geändert" + password_resets: + create: + check_email_reset_instructions: "Überprüfen Sie Ihre E-Mail auf Anweisungen zum Zurücksetzen" + cant_reset_until_verified: "Sie können Ihr Passwort erst zurücksetzen, nachdem Sie Ihre E-Mail verifiziert haben" + update: + password_reset_success: "Ihr Passwort wurde erfolgreich zurückgesetzt. Bitte melden Sie sich an" + set_user: + invalid_reset_link: "Dieser Link zum Zurücksetzen des Passworts ist ungültig" + sessions: + omniauth: + create: + signed_in_successfully: "Erfolgreich angemeldet" + authentication_failed: "Authentifizierung fehlgeschlagen" + passwordlesses: + edit: + signed_in_successfully: "Erfolgreich angemeldet" + create: + check_email_sign_in_instructions: "Überprüfen Sie Ihre E-Mail auf Anweisungen zur Anmeldung" + cant_sign_in_until_verified: "Sie können sich erst anmelden, nachdem Sie Ihre E-Mail verifiziert haben" + set_user: + invalid_sign_in_link: "Dieser Anmeldelink ist ungültig" + sudos: + create: + incorrect_password: "Das eingegebene Passwort ist falsch" + two_factor_authentication: + challenge: + recovery_codes: + create: + code_didnt_work: "Dieser Code hat nicht funktioniert. Bitte versuchen Sie es erneut" + set_user: + taking_too_long: "Das dauert zu lange. Bitte geben Sie Ihr Passwort erneut ein und versuchen Sie es noch einmal" + security_keys: + create: + verification_failed: "Verifizierung fehlgeschlagen: %{error}" + set_user: + taking_too_long: "Das dauert zu lange. Bitte geben Sie Ihr Passwort erneut ein und versuchen Sie es noch einmal" + totps: + create: + code_didnt_work: "Dieser Code hat nicht funktioniert. Bitte versuchen Sie es erneut" + set_user: + taking_too_long: "Das dauert zu lange. Bitte geben Sie Ihr Passwort erneut ein und versuchen Sie es noch einmal" + profile: + recovery_codes: + create: + new_codes_generated: "Ihre neuen Wiederherstellungscodes wurden generiert" + security_keys: + update: + changes_saved: "Ihre Änderungen wurden gespeichert" + destroy: + security_key_removed: "%{name} wurde entfernt" + totps: + create: + code_didnt_work: "Dieser Code hat nicht funktioniert. Bitte versuchen Sie es erneut" + user_mailer: + subjects: + password_reset: "Ihr Passwort zurücksetzen" + email_verification: "Ihre E-Mail verifizieren" + passwordless: "Ihr Anmeldelink" + invitation_instructions: "Einladungsanweisungen" + email_verification: + greeting: "Hallo," + confirmation_text: "Dies bestätigt, dass %{email} die E-Mail-Adresse ist, die Sie für Ihr Konto verwenden möchten. Wenn Sie jemals Ihr Passwort vergessen, senden wir den Reset-Link dorthin." + must_confirm: "Sie müssen den unten stehenden Link anklicken, um zu bestätigen, dass Sie diese E-Mail erhalten haben." + confirm_link: "Ja, verwenden Sie diese E-Mail für mein Konto" + help_text: "Haben Sie Fragen oder brauchen Sie Hilfe? Antworten Sie einfach auf diese E-Mail und unser Support-Team wird Ihnen helfen." + invitation_instructions: + greeting: "Hallo," + invitation_text: "Jemand hat Sie zu der Anwendung eingeladen, Sie können sie über den unten stehenden Link akzeptieren." + accept_invitation: "Einladung akzeptieren" + ignore_text: "Wenn Sie die Einladung nicht akzeptieren möchten, ignorieren Sie diese E-Mail bitte. Ihr Konto wird erst erstellt, wenn Sie den oben stehenden Link aufrufen und Ihr Passwort festlegen." + help_text: "Haben Sie Fragen oder brauchen Sie Hilfe? Antworten Sie einfach auf diese E-Mail und unser Support-Team wird Ihnen helfen." + password_reset: + greeting: "Hallo," + reset_text: "Können Sie sich nicht an Ihr Passwort für %{email} erinnern? Das ist in Ordnung, das passiert. Klicken Sie einfach den unten stehenden Link, um ein neues zu erstellen." + reset_link: "Mein Passwort zurücksetzen" + ignore_text: "Wenn Sie kein Zurücksetzen des Passworts angefordert haben, können Sie diese E-Mail sicher ignorieren. Sie läuft in 20 Minuten ab. Nur jemand mit Zugriff auf dieses E-Mail-Konto kann Ihr Passwort zurücksetzen." + help_text: "Haben Sie Fragen oder brauchen Sie Hilfe? Antworten Sie einfach auf diese E-Mail und unser Support-Team wird Ihnen helfen." + passwordless: + greeting: "Hallo," + magic_link_text: "Sie haben einen magischen Anmeldelink angefordert. Hier ist er:" + sign_in_link: "Ohne Passwort anmelden" + help_text: "Haben Sie Fragen oder brauchen Sie Hilfe? Antworten Sie einfach auf diese E-Mail und unser Support-Team wird Ihnen helfen." \ No newline at end of file diff --git a/lib/authentication_zero/locales/ja.yml b/lib/authentication_zero/locales/ja.yml new file mode 100644 index 00000000..ebcc967f --- /dev/null +++ b/lib/authentication_zero/locales/ja.yml @@ -0,0 +1,270 @@ +ja: + authentication_zero: + home: + index: + signed_as: "%{email}としてログイン中" + login_and_verification: "ログインと認証" + change_password: "パスワードを変更" + change_email_address: "メールアドレスを変更" + two_factor_authentication: "2要素認証" + recovery_codes: "リカバリーコード" + security_keys: "セキュリティキー" + send_invitation: "招待を送信" + signin_as_last_user: "最後のユーザーとしてログイン" + access_history: "アクセス履歴" + devices_sessions: "デバイスとセッション" + activity_log: "アクティビティログ" + log_out: "ログアウト" + authentications: + events: + index: + activity_log: "アクティビティログ" + user_agent: "ユーザーエージェント:" + action: "アクション:" + ip_address: "IPアドレス:" + created_at: "作成日時:" + back: "戻る" + identity: + emails: + edit: + change_your_email: "メールアドレスを変更" + verify_your_email: "メールアドレスを認証" + verification_sent: "下記のアドレスに認証メールを送信しました。このメールを確認し、指示に従ってメールアドレスがあなたのものかを確認してください。" + re_send_verification_email: "認証メールを再送信" + new_email: "新しいメールアドレス" + password_challenge: "パスワード確認" + save_changes: "変更を保存" + back: "戻る" + password_resets: + edit: + reset_your_password: "パスワードをリセット" + new_password: "新しいパスワード" + confirm_new_password: "新しいパスワードを確認" + password_minimum: "12文字以上。" + save_changes: "変更を保存" + new: + forgot_your_password: "パスワードをお忘れですか?" + send_password_reset_email: "パスワードリセットメールを送信" + invitations: + new: + send_invitation: "招待を送信" + send_an_invitation: "招待を送信" + back: "戻る" + passwords: + edit: + change_your_password: "パスワードを変更" + new_password: "新しいパスワード" + confirm_new_password: "新しいパスワードを確認" + password_minimum: "12文字以上。" + save_changes: "変更を保存" + back: "戻る" + registrations: + new: + sign_up: "新規登録" + password_minimum: "12文字以上。" + sessions: + index: + devices_sessions: "デバイスとセッション" + user_agent: "ユーザーエージェント:" + ip_address: "IPアドレス:" + created_at: "作成日時:" + log_out: "ログアウト" + back: "戻る" + new: + sign_in: "ログイン" + sign_in_without_password: "パスワードなしでログイン" + sign_in_with_omniauth: "OmniAuthでログイン" + sign_up: "新規登録" + forgot_your_password: "パスワードをお忘れですか?" + passwordlesses: + new: + sign_in_without_password: "パスワードなしでログイン" + sign_in: "ログイン" + sudos: + new: + enter_password_to_continue: "続行するにはパスワードを入力してください" + continue: "続行" + why_asking: "なぜこれを尋ねるのですか?" + protection_explanation: "アカウントをより安全に保護するため、機密性の高い操作を実行する前にパスワードの確認をお願いする場合があります。" + forgot_password: "パスワードをお忘れですか?" + reset_help: "続行できるように%{link}いたします。" + reset_link_text: "リセット" + two_factor_authentication: + challenge: + recovery_codes: + new: + enter_recovery_code: "OK、下記にリカバリーコードのいずれかを入力してください:" + continue: "続行" + access_instructions: "アカウントにアクセスするには、2要素認証デバイスを設定した際に保存したリカバリーコード(例:xxxxxxxxxx)のいずれかを入力してください。" + security_keys: + new: + verify_with_security_key: "セキュリティキーで認証してください。" + use_security_key: "セキュリティキーを使用" + security_key_instructions: "セキュリティキーを準備してください。USBタイプの場合は今すぐ挿入し、求められたらアクティベーションキーを押してください。" + totps: + new: + enter_2fa_code: "次に、電話の2FA認証アプリを開き、下記の6桁のコードを入力してください:" + verify: "認証" + dont_have_phone: "電話をお持ちですか?" + use_recovery_code: "リカバリーコードを使用してアカウントにアクセス" + use_security_key: "セキュリティキーを使用してアカウントにアクセス" + profile: + recovery_codes: + index: + two_factor_recovery_codes: "2要素認証リカバリーコード" + recovery_codes_description: "リカバリーコードは、電話を紛失した場合(または手元にない場合)にログインする方法を提供します。これらを保存し、安全な場所に保管してください。" + ok_done: "OK、完了しました" + need_new_codes: "新しいリカバリーコードが必要ですか?" + new_codes_warning: "コードが第三者の手に渡ったと思われる場合は、新しいセットを取得できます。新しいコードを保存してください。古いコードは機能しなくなります。" + generate_new_codes: "新しいリカバリーコードを生成" + security_keys: + _form_confirm: + one_more_step: "もう一つのステップ。このセキュリティキーに覚えやすいニックネームを付けてください。" + name: "名前" + example: "例:Macbook Touch ID" + save: "保存" + _form_edit: + name: "名前" + example: "例:Macbook Touch ID" + save_changes: "変更を保存" + remove_security_key: "このセキュリティキーを削除..." + edit: + edit_security_key: "セキュリティキーを編集" + index: + security_keys: "セキュリティキー" + security_keys_description: "セキュリティキーは、IDを認証するために使用されるハードウェアデバイスです。例えば、組み込みの指紋リーダー、USBキー、またはWindows Helloのようなログオンシステムです。" + add_security_key: "セキュリティキーを追加" + back: "戻る" + new: + add_security_key: "セキュリティキーを追加" + ready_instructions: "セキュリティキーを準備してください。USBタイプの場合は今すぐ挿入し、求められたらアクティベーションキーを押してください。" + im_ready: "準備できました、始めましょう" + totps: + new: + replace_existing_2fa: "既存の2FA設定を置き換えますか?" + already_protected: "あなたのアカウントはすでに2要素認証で保護されています。新しく電話や認証アプリに切り替える場合は、この設定を置き換えることができます。" + continue_warning: "続行しますか?既存の2FA設定は機能しなくなります。" + yes_replace: "はい、2FA設定を置き換えます" + upgrade_security: "2FAでセキュリティを強化" + step1_get_app: "ステップ1:認証アプリを入手" + get_app_instructions: "まず、電話に2FA認証アプリが必要です。%{strong_text}" + skip_if_have: "すでに持っている場合はステップ2をスキップしてください。" + recommend_app: "持っていない場合や不明な場合は、Microsoft Authenticatorをお勧めします。iPhone版はApple App Store、Android版はGoogle Play Storeで無料ダウンロードできます。今すぐ電話を取り、ストアで検索してインストールしてください。" + step2_scan_enter: "ステップ2:スキャンしてコードを入力" + scan_instructions: "次に、認証アプリを開き、「QRコードをスキャン」または「+」をタップし、求められたら電話のカメラを下記のQRコード画像に向けます。" + point_camera: "カメラをここに向ける" + enter_code_instructions: "カメラでスキャンした後、アプリが6桁のコードを生成します。ここに入力してください:" + verify_activate: "認証して有効化" + back: "戻る" + controllers: + invitations: + create: + invitation_sent: "%{email}に招待メールが送信されました" + masquerades: + create: + signed_in_successfully: "ログインに成功しました" + authorize: + must_be_in_development: "開発環境である必要があります" + passwords: + update: + password_changed: "パスワードが変更されました" + registrations: + create: + welcome_signed_up: "ようこそ!登録が完了しました" + sessions: + create: + signed_in_successfully: "ログインに成功しました" + incorrect_email_or_password: "メールアドレスまたはパスワードが正しくありません" + destroy: + session_logged_out: "このセッションはログアウトされました" + identity: + email_verifications: + show: + thank_you_verified: "メールアドレスの認証ありがとうございます" + create: + verification_email_sent: "メールアドレスに認証メールを送信しました" + emails: + update: + email_changed: "メールアドレスが変更されました" + password_resets: + create: + check_email_reset_instructions: "リセット手順をメールで確認してください" + cant_reset_until_verified: "メール認証後にパスワードをリセットできます" + update: + password_reset_success: "パスワードが正常にリセットされました。ログインしてください" + set_user: + invalid_reset_link: "このパスワードリセットリンクは無効です" + sessions: + omniauth: + create: + signed_in_successfully: "ログインに成功しました" + authentication_failed: "認証に失敗しました" + passwordlesses: + edit: + signed_in_successfully: "ログインに成功しました" + create: + check_email_sign_in_instructions: "ログイン手順をメールで確認してください" + cant_sign_in_until_verified: "メール認証後にログインできます" + set_user: + invalid_sign_in_link: "このログインリンクは無効です" + sudos: + create: + incorrect_password: "入力されたパスワードが正しくありません" + two_factor_authentication: + challenge: + recovery_codes: + create: + code_didnt_work: "このコードは機能しませんでした。もう一度お試しください" + set_user: + taking_too_long: "時間がかかりすぎています。パスワードを再入力して、もう一度お試しください" + security_keys: + create: + verification_failed: "認証に失敗しました:%{error}" + set_user: + taking_too_long: "時間がかかりすぎています。パスワードを再入力して、もう一度お試しください" + totps: + create: + code_didnt_work: "このコードは機能しませんでした。もう一度お試しください" + set_user: + taking_too_long: "時間がかかりすぎています。パスワードを再入力して、もう一度お試しください" + profile: + recovery_codes: + create: + new_codes_generated: "新しいリカバリーコードが生成されました" + security_keys: + update: + changes_saved: "変更が保存されました" + destroy: + security_key_removed: "%{name}が削除されました" + totps: + create: + code_didnt_work: "このコードは機能しませんでした。もう一度お試しください" + user_mailer: + subjects: + password_reset: "パスワードをリセット" + email_verification: "メールアドレスを認証" + passwordless: "ログインリンク" + invitation_instructions: "招待手順" + email_verification: + greeting: "こんにちは、" + confirmation_text: "%{email}があなたのアカウントで使用したいメールアドレスであることを確認します。パスワードを忘れた場合、このアドレスにリセットリンクを送信します。" + must_confirm: "このメールを受け取ったことを確認するため、下記のリンクをクリックする必要があります。" + confirm_link: "はい、このメールをアカウントに使用します" + help_text: "ご質問やお困りですか?このメールに返信していただければ、サポートチームがお手伝いいたします。" + invitation_instructions: + greeting: "こんにちは、" + invitation_text: "誰かがあなたをアプリケーションに招待しました。下記のリンクから受け入れることができます。" + accept_invitation: "招待を受け入れる" + ignore_text: "招待を受けたくない場合は、このメールを無視してください。上記のリンクにアクセスしてパスワードを設定するまで、アカウントは作成されません。" + help_text: "ご質問やお困りですか?このメールに返信していただければ、サポートチームがお手伝いいたします。" + password_reset: + greeting: "こんにちは、" + reset_text: "%{email}のパスワードを思い出せませんか?大丈夫です。そんな時は下記のリンクから新しいパスワードを作成してください。" + reset_link: "パスワードをリセット" + ignore_text: "パスワードのリセットをリクエストしていない場合は、このメールを無視してください。20分後に有効期限が切れます。このメールアカウントにアクセスできる人だけがパスワードをリセットできます。" + help_text: "ご質問やお困りですか?このメールに返信していただければ、サポートチームがお手伝いいたします。" + passwordless: + greeting: "こんにちは、" + magic_link_text: "マジックログインリンクをリクエストしました。こちらです:" + sign_in_link: "パスワードなしでログイン" + help_text: "ご質問やお困りですか?このメールに返信していただければ、サポートチームがお手伝いいたします。" \ No newline at end of file From a7666ff659ca8f0ecf5ddc7b762a3b4c54474efd Mon Sep 17 00:00:00 2001 From: Benedikt Laube Date: Tue, 21 Oct 2025 11:59:14 +0200 Subject: [PATCH 08/13] Add i18n locale file generator --- lib/generators/i18n/i18n_generator.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 lib/generators/i18n/i18n_generator.rb diff --git a/lib/generators/i18n/i18n_generator.rb b/lib/generators/i18n/i18n_generator.rb new file mode 100644 index 00000000..eb6143fc --- /dev/null +++ b/lib/generators/i18n/i18n_generator.rb @@ -0,0 +1,15 @@ +require "rails/generators" + +module AuthenticationZero + module Generators + class I18nGenerator < Rails::Generators::Base + desc "Copies Authentication Zero i18n locale files for en, de, ja locales into your application for customization." + + source_root File.expand_path("templates", __dir__) + + def copy_locales + directory "locales", "config/locales/authentication_zero" + end + end + end +end \ No newline at end of file From 952cd3711b2cc10183b81dbed10412c30ca863ee Mon Sep 17 00:00:00 2001 From: Benedikt Laube Date: Tue, 21 Oct 2025 12:32:16 +0200 Subject: [PATCH 09/13] Mention i18n in options --- README.md | 1 + .../i18n/templates}/locales/de.yml | 0 .../i18n/templates}/locales/en.yml | 0 .../i18n/templates}/locales/ja.yml | 0 4 files changed, 1 insertion(+) rename lib/{authentication_zero => generators/i18n/templates}/locales/de.yml (100%) rename lib/{authentication_zero => generators/i18n/templates}/locales/en.yml (100%) rename lib/{authentication_zero => generators/i18n/templates}/locales/ja.yml (100%) diff --git a/README.md b/README.md index 88582305..204d1d86 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ Since Authentication Zero generates this code into your application instead of b - Send invitations (--invitable) - "Sign-in as" button (--masqueradable) - Multi-tentant application (--tenantable) +- Add default locale files for en, de, ja (--i18n) ## Generated code diff --git a/lib/authentication_zero/locales/de.yml b/lib/generators/i18n/templates/locales/de.yml similarity index 100% rename from lib/authentication_zero/locales/de.yml rename to lib/generators/i18n/templates/locales/de.yml diff --git a/lib/authentication_zero/locales/en.yml b/lib/generators/i18n/templates/locales/en.yml similarity index 100% rename from lib/authentication_zero/locales/en.yml rename to lib/generators/i18n/templates/locales/en.yml diff --git a/lib/authentication_zero/locales/ja.yml b/lib/generators/i18n/templates/locales/ja.yml similarity index 100% rename from lib/authentication_zero/locales/ja.yml rename to lib/generators/i18n/templates/locales/ja.yml From cef48510bdfafd572d62760d4510572098442a25 Mon Sep 17 00:00:00 2001 From: Benedikt Laube Date: Tue, 21 Oct 2025 12:32:42 +0200 Subject: [PATCH 10/13] Remove dependency on rails-i18n (because it is an optional feature) --- authentication-zero.gemspec | 2 -- 1 file changed, 2 deletions(-) diff --git a/authentication-zero.gemspec b/authentication-zero.gemspec index b26a0040..37c0f132 100644 --- a/authentication-zero.gemspec +++ b/authentication-zero.gemspec @@ -20,6 +20,4 @@ Gem::Specification.new do |spec| `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } end - # For translations, depend on the i18n gem - spec.add_dependency "i18n", "~> 7.0" end From be123b486bc32574180a468d9ff4c4b74ecfa29e Mon Sep 17 00:00:00 2001 From: Benedikt Laube Date: Tue, 21 Oct 2025 12:33:00 +0200 Subject: [PATCH 11/13] Add i18n option to generator --- .../authentication/authentication_generator.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/generators/authentication/authentication_generator.rb b/lib/generators/authentication/authentication_generator.rb index ad0b807e..8c9470c3 100644 --- a/lib/generators/authentication/authentication_generator.rb +++ b/lib/generators/authentication/authentication_generator.rb @@ -15,6 +15,7 @@ class AuthenticationGenerator < Rails::Generators::Base class_option :invitable, type: :boolean, desc: "Add sending invitations" class_option :masqueradable, type: :boolean, desc: "Add sign-in as button functionallity" class_option :tenantable, type: :boolean, desc: "Add artifacts to implement a row-level tenant app" + class_option :i18n, type: :boolean, desc: "Add default locale files (en, de, ja) to config/locales/authentication" source_root File.expand_path("templates", __dir__) @@ -42,6 +43,10 @@ def add_gems if webauthn? gem "webauthn", comment: "Use webauthn for making rails become a conformant web authn relying party [https://github.com/cedarcode/webauthn-ruby]" end + + if i18n? + gem "rails-i18n", "~> 8.0.0", comment: "Use rails-i18n gem for translation [https://github.com/svenfuchs/rails-i18n]" + end end def create_configuration_files @@ -206,6 +211,13 @@ def add_routes route 'get "sign_in", to: "sessions#new"' unless options.api? end + def copy_i18n_files + if options.i18n? + # Copy from locales to app + directory "i18n/locales", "config/locales/authentication", force: false + end + end + def create_test_files directory "test_unit/controllers/#{format}", "test/controllers" directory "test_unit/mailers/", "test/mailers" @@ -256,4 +268,8 @@ def importmaps? def node? Rails.root.join("package.json").exist? end + + def i18n? + options.i18n? + end end From 6a6f36c25659e58b37fe2525829c6aa6716fae40 Mon Sep 17 00:00:00 2001 From: Benedikt Laube Date: Tue, 21 Oct 2025 12:33:51 +0200 Subject: [PATCH 12/13] Remove custom generator and move default locale files to authentication generator template path --- .../templates/i18n}/locales/de.yml | 0 .../templates/i18n}/locales/en.yml | 0 .../templates/i18n}/locales/ja.yml | 0 lib/generators/i18n/i18n_generator.rb | 15 --------------- 4 files changed, 15 deletions(-) rename lib/generators/{i18n/templates => authentication/templates/i18n}/locales/de.yml (100%) rename lib/generators/{i18n/templates => authentication/templates/i18n}/locales/en.yml (100%) rename lib/generators/{i18n/templates => authentication/templates/i18n}/locales/ja.yml (100%) delete mode 100644 lib/generators/i18n/i18n_generator.rb diff --git a/lib/generators/i18n/templates/locales/de.yml b/lib/generators/authentication/templates/i18n/locales/de.yml similarity index 100% rename from lib/generators/i18n/templates/locales/de.yml rename to lib/generators/authentication/templates/i18n/locales/de.yml diff --git a/lib/generators/i18n/templates/locales/en.yml b/lib/generators/authentication/templates/i18n/locales/en.yml similarity index 100% rename from lib/generators/i18n/templates/locales/en.yml rename to lib/generators/authentication/templates/i18n/locales/en.yml diff --git a/lib/generators/i18n/templates/locales/ja.yml b/lib/generators/authentication/templates/i18n/locales/ja.yml similarity index 100% rename from lib/generators/i18n/templates/locales/ja.yml rename to lib/generators/authentication/templates/i18n/locales/ja.yml diff --git a/lib/generators/i18n/i18n_generator.rb b/lib/generators/i18n/i18n_generator.rb deleted file mode 100644 index eb6143fc..00000000 --- a/lib/generators/i18n/i18n_generator.rb +++ /dev/null @@ -1,15 +0,0 @@ -require "rails/generators" - -module AuthenticationZero - module Generators - class I18nGenerator < Rails::Generators::Base - desc "Copies Authentication Zero i18n locale files for en, de, ja locales into your application for customization." - - source_root File.expand_path("templates", __dir__) - - def copy_locales - directory "locales", "config/locales/authentication_zero" - end - end - end -end \ No newline at end of file From e4206aae376c5f0c1cf3fe91f8cfa53063661ffa Mon Sep 17 00:00:00 2001 From: Benedikt Laube Date: Tue, 21 Oct 2025 14:52:23 +0200 Subject: [PATCH 13/13] Add i18n decorators to form labels that did not have them. Also add the translations --- .../erb/identity/password_resets/new.html.erb.tt | 2 +- .../templates/erb/invitations/new.html.erb.tt | 2 +- .../templates/erb/registrations/new.html.erb.tt | 6 +++--- .../authentication/templates/erb/sessions/new.html.erb.tt | 4 ++-- .../templates/erb/sessions/passwordlesses/new.html.erb.tt | 2 +- .../authentication/templates/i18n/locales/de.yml | 8 ++++++++ .../authentication/templates/i18n/locales/en.yml | 8 ++++++++ .../authentication/templates/i18n/locales/ja.yml | 8 ++++++++ 8 files changed, 32 insertions(+), 8 deletions(-) diff --git a/lib/generators/authentication/templates/erb/identity/password_resets/new.html.erb.tt b/lib/generators/authentication/templates/erb/identity/password_resets/new.html.erb.tt index c58c564f..a6b24ab2 100644 --- a/lib/generators/authentication/templates/erb/identity/password_resets/new.html.erb.tt +++ b/lib/generators/authentication/templates/erb/identity/password_resets/new.html.erb.tt @@ -4,7 +4,7 @@ <%%= form_with(url: identity_password_reset_path) do |form| %>
- <%%= form.label :email, style: "display: block" %> + <%%= form.label :email, t('authentication_zero.identity.password_resets.new.email'), style: "display: block" %> <%%= form.email_field :email, required: true, autofocus: true %>
diff --git a/lib/generators/authentication/templates/erb/invitations/new.html.erb.tt b/lib/generators/authentication/templates/erb/invitations/new.html.erb.tt index 267620f5..45b90db2 100644 --- a/lib/generators/authentication/templates/erb/invitations/new.html.erb.tt +++ b/lib/generators/authentication/templates/erb/invitations/new.html.erb.tt @@ -16,7 +16,7 @@ <%% end %>
- <%%= form.label :email, style: "display: block" %> + <%%= form.label :email, t('authentication_zero.invitations.new.email'), style: "display: block" %> <%%= form.email_field :email, required: true, autofocus: true %>
diff --git a/lib/generators/authentication/templates/erb/registrations/new.html.erb.tt b/lib/generators/authentication/templates/erb/registrations/new.html.erb.tt index 0a46b57d..01c750a7 100644 --- a/lib/generators/authentication/templates/erb/registrations/new.html.erb.tt +++ b/lib/generators/authentication/templates/erb/registrations/new.html.erb.tt @@ -14,18 +14,18 @@ <%% end %>
- <%%= form.label :email, style: "display: block" %> + <%%= form.label :email, t('authentication_zero.registrations.new.email'), style: "display: block" %> <%%= form.email_field :email, value: @user.email, required: true, autofocus: true, autocomplete: "email" %>
- <%%= form.label :password, style: "display: block" %> + <%%= form.label :password, t('authentication_zero.registrations.new.password'), style: "display: block" %> <%%= form.password_field :password, required: true, autocomplete: "new-password" %>
<%%= t('authentication_zero.registrations.new.password_minimum') %>
- <%%= form.label :password_confirmation, style: "display: block" %> + <%%= form.label :password_confirmation, t('authentication_zero.registrations.new.password_confirmation'), style: "display: block" %> <%%= form.password_field :password_confirmation, required: true, autocomplete: "new-password" %>
diff --git a/lib/generators/authentication/templates/erb/sessions/new.html.erb.tt b/lib/generators/authentication/templates/erb/sessions/new.html.erb.tt index 9f48f195..94e2c71f 100644 --- a/lib/generators/authentication/templates/erb/sessions/new.html.erb.tt +++ b/lib/generators/authentication/templates/erb/sessions/new.html.erb.tt @@ -5,12 +5,12 @@ <%%= form_with(url: sign_in_path) do |form| %>
- <%%= form.label :email, style: "display: block" %> + <%%= form.label :email, t('authentication_zero.sessions.new.email'), style: "display: block" %> <%%= form.email_field :email, value: params[:email_hint], required: true, autofocus: true, autocomplete: "email" %>
- <%%= form.label :password, style: "display: block" %> + <%%= form.label :password, t('authentication_zero.sessions.new.password'), style: "display: block" %> <%%= form.password_field :password, required: true, autocomplete: "current-password" %>
diff --git a/lib/generators/authentication/templates/erb/sessions/passwordlesses/new.html.erb.tt b/lib/generators/authentication/templates/erb/sessions/passwordlesses/new.html.erb.tt index daf221aa..698ff036 100644 --- a/lib/generators/authentication/templates/erb/sessions/passwordlesses/new.html.erb.tt +++ b/lib/generators/authentication/templates/erb/sessions/passwordlesses/new.html.erb.tt @@ -4,7 +4,7 @@ <%%= form_with(url: sessions_passwordless_path) do |form| %>
- <%%= form.label :email, style: "display: block" %> + <%%= form.label :email, t('authentication_zero.sessions.passwordlesses.new.email'), style: "display: block" %> <%%= form.email_field :email, required: true, autofocus: true %>
diff --git a/lib/generators/authentication/templates/i18n/locales/de.yml b/lib/generators/authentication/templates/i18n/locales/de.yml index 24f55ff9..ebd86829 100644 --- a/lib/generators/authentication/templates/i18n/locales/de.yml +++ b/lib/generators/authentication/templates/i18n/locales/de.yml @@ -44,10 +44,12 @@ de: save_changes: "Änderungen speichern" new: forgot_your_password: "Passwort vergessen?" + email: "E-Mail" send_password_reset_email: "E-Mail zum Zurücksetzen des Passworts senden" invitations: new: send_invitation: "Einladung senden" + email: "E-Mail" send_an_invitation: "Eine Einladung senden" back: "Zurück" passwords: @@ -61,6 +63,9 @@ de: registrations: new: sign_up: "Registrieren" + email: "E-Mail" + password: "Passwort" + password_confirmation: "Passwort-Bestätigung" password_minimum: "Mindestens 12 Zeichen." sessions: index: @@ -72,6 +77,8 @@ de: back: "Zurück" new: sign_in: "Anmelden" + email: "E-Mail" + password: "Passwort" sign_in_without_password: "Ohne Passwort anmelden" sign_in_with_omniauth: "Mit OmniAuth anmelden" sign_up: "Registrieren" @@ -79,6 +86,7 @@ de: passwordlesses: new: sign_in_without_password: "Ohne Passwort anmelden" + email: "E-Mail" sign_in: "Anmelden" sudos: new: diff --git a/lib/generators/authentication/templates/i18n/locales/en.yml b/lib/generators/authentication/templates/i18n/locales/en.yml index c411eb2a..203232e8 100644 --- a/lib/generators/authentication/templates/i18n/locales/en.yml +++ b/lib/generators/authentication/templates/i18n/locales/en.yml @@ -44,10 +44,12 @@ en: save_changes: "Save changes" new: forgot_your_password: "Forgot your password?" + email: "Email" send_password_reset_email: "Send password reset email" invitations: new: send_invitation: "Send invitation" + email: "Email" send_an_invitation: "Send an invitation" back: "Back" passwords: @@ -61,6 +63,9 @@ en: registrations: new: sign_up: "Sign up" + email: "Email" + password: "Password" + password_confirmation: "Password confirmation" password_minimum: "12 characters minimum." sessions: index: @@ -72,6 +77,8 @@ en: back: "Back" new: sign_in: "Sign in" + email: "Email" + password: "Password" sign_in_without_password: "Sign in without password" sign_in_with_omniauth: "Sign in with OmniAuth" sign_up: "Sign up" @@ -79,6 +86,7 @@ en: passwordlesses: new: sign_in_without_password: "Sign in without password" + email: "Email" sign_in: "Sign in" sudos: new: diff --git a/lib/generators/authentication/templates/i18n/locales/ja.yml b/lib/generators/authentication/templates/i18n/locales/ja.yml index ebcc967f..8d05eb51 100644 --- a/lib/generators/authentication/templates/i18n/locales/ja.yml +++ b/lib/generators/authentication/templates/i18n/locales/ja.yml @@ -44,10 +44,12 @@ ja: save_changes: "変更を保存" new: forgot_your_password: "パスワードをお忘れですか?" + email: "メールアドレス" send_password_reset_email: "パスワードリセットメールを送信" invitations: new: send_invitation: "招待を送信" + email: "メールアドレス" send_an_invitation: "招待を送信" back: "戻る" passwords: @@ -61,6 +63,9 @@ ja: registrations: new: sign_up: "新規登録" + email: "メールアドレス" + password: "パスワード" + password_confirmation: "パスワード確認" password_minimum: "12文字以上。" sessions: index: @@ -72,6 +77,8 @@ ja: back: "戻る" new: sign_in: "ログイン" + email: "メールアドレス" + password: "パスワード" sign_in_without_password: "パスワードなしでログイン" sign_in_with_omniauth: "OmniAuthでログイン" sign_up: "新規登録" @@ -79,6 +86,7 @@ ja: passwordlesses: new: sign_in_without_password: "パスワードなしでログイン" + email: "メールアドレス" sign_in: "ログイン" sudos: new: