I have a problem with a Rails 2.3.8 application. I'm using rails i18n to make the site in different languages. Everything works perfect, everywhere, except one place.
After successful signup, I do:
flash[:notice] = t 'path.to.locale.key'
Just as I do everywhere else.
But that renders the following:
translation missing: 'locale.path.to.locale.key' not found
It seems it's not loading the current locale (or else it will say 'en', or 'es', or whatever instead of 'locale').
Any idea that could be causing this?
Thanks
Maybe you overwrite it somewhere down that yml file. Maybe you did too many nesting. Maybe that key has subkeys.
Delete everything from that locale.yml and place only that message and see if it works.
The problem you are having happens to me every now and then, and it's always something I messed up in yml file.
Try setting a default locale in your ApplicationController, for example with a before_filter:
I18n.locale = params[:locale] || 'en'
Well, this happened to me in mailer classes after I upgraded to Rails 4.1. It was working correctly on Rails 3 and there was no change on yml files. Somehow i18n did not see the default locale.
So I've added this line on mailer class to fix out.
I18n.locale = I18n.default_locale
class ProviderMailer < ActionMailer::Base
include Resque::Mailer
default from: APP_CONFIG.mailer.from
def registration_email(provider)
#provider = provider
I18n.locale = I18n.default_locale
#provider_url = "#{APP_CONFIG.base_url}/hizmetsgl/#{provider['_id']}"
#howto_url = "#{APP_CONFIG.base_url}/hizmetverenler"
mail(to: provider["business_email"], subject: t('provider_mailer.registration_email.subject'))
end
end
Related
I have a model with custom validations. I return the validation
errors to the view as JSON using AJAX.
I need to show the error
messages with the right locale but the messages
show in English (default) for each locale.
When I return I18n.locale
itself instead of the message (for troubleshooting) it shows "en" no matter what is the set locale.
I18n in controllers or views works as expected, this problem
occurs only in the model.
The only configuration that I've made regarding locale is setting the default locale in the application config and setting the locale before each action in the application controller.
Another thing that I've noticed is that when I use root_path without providing the locale, it's using the default locale instead keeping the current locale like it should. I think those issues are connected
Edit:
When I print the locale parameter in controller#create, I get nil. For some reason I don't have the locale parameter at all.
model file:
validate :relevant_date_time
def relevant_date_time
errors.add(:date_error, I18n.t("validations.date_error")) unless date_time_is_relevant?
end
application_controller:
before_action :set_locale
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
end
Am I forgetting something?
Information I reviewed:
http://guides.rubyonrails.org/i18n.html
Access translation file (i18n) from inside rails model
Rails 3 translations within models in production
http://www.eq8.eu/blogs/10-translating-locales-for-rails-model-errors
https://lingohub.com/frameworks-file-formats/rails5-i18n-ruby-on-rails/
Change locale at runtime in Rails 3
If you set locale at application_controller.rb, it will only have scope in all controllers and views NOT in models.
So you have to set locale inside model too. Same as you did at controller.
At controller
Model.new(params.merge(locale: I18n.locale))
Inside model
attr_accessible :locale
before_validation() do
I18n.local = locale
end
def relevant_date_time
errors.add(:date_error, I18n.t("validations.date_error")) unless date_time_is_relevant?
end
I18n locale in controllers/views only applies to the action's context, it does not change your app's default locale setting, which is where your model is getting its locale from (as you have discovered).
The step you are missing is to pass the locale into your model from your action, which you could do by adding an attr_accessor :locale to your model, and then passing the locale through when creating/updating it in your controller:
# e.g. app/controllers/users_controller.rb
# user_params = { email: test#mail.com, password: 12345678 }
User.new(user_params.merge(locale: I18n.locale))
Then in your validation method you would be able to access the current locale with locale, so all you need to do is pass it to I18n.t:
errors.add(:date_error, I18n.t("validations.date_error", locale: locale)) unless date_time_is_relevant?
Solved by adding the following method in application controller:
def default_url_options(options={})
{ locale: I18n.locale }
end
For anyone who is struggling with I18n in model validation, the solution could be not including any custom message keys in the models but
en:
activerecord:
errors:
models:
model_name:
attributes:
attr_name:
taken: << or whatever error message like blank, too_long, too_short etc.
Credit t:
https://stackoverflow.com/a/4453350/267693
I have a PetsController in which a flash message is setted. Something like this:
class PetsController
...
def treat_dog
#do somthing
flash[:success] = 'Your dog is being treated.'
end
...
end
this controller belongs to Admin, so it is located at: app/controllers/admin/pets_controller.rb. I will use I18n, so I replaced the string in controller with t('controllers.admin.pet.treated'), then,I wrote this yml:
en:
controllers:
admin:
pet:
treated: "Your dog is being treated."
located at: config/locales/controllers/admin/pet/en.yml and it did not work. I have attempted locating it at config/locales/controllers/admin/pets/en.yml, config/locales/controllers/admin/en.yml
config/locales/controllers/en.yml
and none of these worked, the translation is not found.
How can I use a translation from this controller?
In controller you use it like this
I18n.t 'controllers.admin.pet.treated'
Using t() directly enables lazy loading:
t(".treated") #loads from key: controllers.admin.pet.treated
def treat_dog
#do somthing
flash[:success] = t('controllers.admin.pet.treated')
end
Put it into config/locales/en.yml and it should work (you may need to restart the server).
This guide should help clear the head about I18n. I'm giving link to relevant section, but read it in full: http://guides.rubyonrails.org/i18n.html#adding-translations
If you insist on using nested files, you need to enable it. Documentation says:
The default locale loading mechanism in Rails does not load locale files in nested dictionaries, like we have here. So, for this to work, we must explicitly tell Rails to look further:
# config/application.rb
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')]
In callback it should be:
add_breadcrumb proc{ I18n.t('home_page') }, :root_path
I'm trying to internationalize a Rails/Spree app using spree's own spree_i18n gem, but I can't get it to work.
I made a minimal app which recreates the problem here.
To cut a long story short, I have the following code in my ApplicationController:
before_action :set_locale
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
puts I18n.locale
end
And code in my view which should be translated (<%= t("whatever") %>). But no matter what I do, the text is always output in English.
With some additional code for debugging, I can see that once set_locale is called but while execution is still within the controller, the locale is correct (e.g. if I visit the url /?locale=es, then the puts statement in the above controller code outputs es).
But by the time execution has reached the view, the locale has somehow been reset to en. (E.g. adding <% raise I18n.locale.to_s %> within the view raises "en" as an error message.)
I've opened an issue on Spree's Github because as far as I can tell I've followed their instructions exactly and it's still not working, but I may still be missing something. Why isn't the locale getting set properly?
(Note: I should add that the Spree.t doesn't work either, not just t.)
EDIT: If you look at the comment on my Github issue, you'll see that I got it working. However, I'm 99% sure that my solution is a hack and there's a better method I should be using. Bounty goes to whoever can tell me what I'm dong wrong.
Spree I18n gives a way to set default language: on config/application.rb with
config.i18n.default_locale = :es
And the possibility of setting the languages to be changed. Perhaps on config/initializers/spree_i18n.rb
SpreeI18n::Config.available_locales = [:en, :es, :de]
SpreeI18n::Config.supported_locales = [:en, :es, :de]
After that, you can remove set_locale on ApplicationController, because it has no effect.
With this at place, it works like a charm.
Edited:
I change the message of error because I want to be sure that it works:
<%= product_description(#product) rescue Spree.t(:product_has_no_description) +
' ' + Spree.t(:action) %>
And I add a new product without description. Running the server at localhost
In english I see: "This product has no description Action"
In spanish I see: "Este producto no tiene descripción Acción"
In deutsch I see: "Produkt hat keine Beschreibung Aktion"
Exactly the expected.
You can see the source with changes at github
It is unclear to me how Spree handles localization and in your routes.rb you only mounts engine.
Basically you should start localize your app within routes.rb by adding:
scope "(:locale)", locale: /#{I18n.available_locales.join("|")}/ do
# routing and engines go here
end
Now, you need to keep your params[:locale] across requests, so add to app controller:
def default_url_options(options={})
logger.debug "default_url_options is passed options: #{options.inspect}\n"
{ locale: I18n.locale }
end
Last, detect and set locale for current request, depending on your input data:
before_filter :set_locale
def set_locale
if defined?(params) && params[:locale]
I18n.locale = params[:locale]
elsif current_user && current_user.language_id.present?
I18n.locale = current_user.language.code
elsif defined?(request)
I18n.locale = extract_locale_from_accept_language_header
end
I18n.locale ||= I18n.default_locale
I18n.locale = :en unless valid_languages.include?(I18n.locale.to_sym)
end
You may be using/setting the following in app/controllers/application_controller.rb, which doesn't work:
before_action :set_locale
def set_locale
I18n.locale =
Spree::Frontend::Config[:locale] =
Spree::Backend::Config[:locale] = :LOCALE
end
In core/lib/spree/core/controller_helpers/common.rb there is another before_filter called set_user_language. That filter gets called and re-sets the locale to the value of session[:locale], or if that's not defined it uses default locale.
To solve the issue, set session[:locale] = :LOCALE in your before_filter.
I am trying to set the local of my users via a field in my user model called locale.
However, the I18n methods do not seem to be working. I'm not sure if I've missed some configuration or something. (I'm still new to rails.) I find that this also happens with many gems that I try to use. Possible that I am initializing things incorrectly?
undefined method default_locale for nil:NilClass
In my Application Controller:
before_filter :set_locale
private
def set_locale # Sets the users language via the locale index.
I18n.default_local = 'en'
I18n.locale = current_user.locale if current_user.locale.present? || I18n.default_locale
end
I am pretty sure that your current_user is nil. Just make sure that the current_user is set before you call locale on it.
For example:
I18n.t('something')
should output only
something
if the translation missing.
It is possible:
See section 4.1.2 Defaults at Rails Internationalization (I18n) API.
I18n.t :missing, :default => 'Not here'
# => 'Not here'
On rails 4 you can change the exception handler.
Add the following to config/initializers/i18n.rb:
module I18n
class MissingTranslationExceptionHandler < ExceptionHandler
def call(exception, locale, key, options)
if exception.is_a?(MissingTranslation)
key
else
super
end
end
end
end
I18n.exception_handler = I18n::MissingTranslationExceptionHandler.new
Now on you views you can just do:
<p><%= t "Not translated!" %></p>
Guide on the subject: http://guides.rubyonrails.org/i18n.html#using-different-exception-handlers
side-note:
this might help figuring out what Rails thinks the current scope is (e.g. when using ".something")
http://unixgods.org/~tilo/Rails/which_l10n_strings_is_rails_trying_to_lookup.html
this way you can better avoid having missing translations because of incorrect placing of translations strings in the L10n-file / incorrect keys
David's answer is the right solution to the question, another (more verbose) way to do it is to rescue and return the key:
def translate_nicely(key)
begin
I18n.translate!(key)
rescue
key
end
end
nope, not possible. If you use I18 you need to have a file that corresponds to the language otherwise I18n will complain.
Of course you can set the default language in your environment.rb file. Should be near the bottom and you can set this for whatever language you want but in your locales/ folder you will need to have a corresponding yml translation.