Heroku does not seem to be loading config/locales/pt.yml
. (Language is being set correctly to pt
.)
I18n is working perfectly on localhost,
I ran into a similar issue, but mine was due to having duplicate keys.
In one file, we defined this:
en:
dashboard: "Dashboard"
And another we defined
en:
dashboard:
title: "Some Title"
Locally, I18n.t("dashboard.title")
worked just fine, but on production it did not. The reason was probably due to a load order difference between Heroku and my development machine.
I fixed it by changing the name of the first dashboard
key so there was no longer an overlap.
Curiously, data were appearing in I18n.backend
as expected but were not individually selectable using I18n.t
This led to the realization that the load path must be configured correctly for Rails to find the translation files, but that it was not parsing them properly.
This led to @ANeves discovering that a BOM was disrupting Heroku's ability to parse the files which resulted in the fix of removing the offending BOM.
The Unicode Standard does permit the BOM in UTF-8, but does not require or recommend its use. Byte order has no meaning in UTF-8 so in UTF-8 the BOM serves only to identify a text stream or file as UTF-8.
Many Windows programs (including Windows Notepad) add BOMs to UTF-8 files by default.
If future readers are on ruby-1.9 consider reading about common encoding problems.
Writing this line will also fix the problem in your application.rb
config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
This issue does not appear to be Heroku-specific and would happen on any Windows/UNIX co-mingling with Ruby / i18n.
@Alexander Wenzowski sent me on the right track.
It seems the byte order mark was messing up Heroku's loading of localization files...
When I converted the files to not have BOM, using Notepad++, everything got fixed.
At first I was just trying to inspect this new thing for me, I18n.backend... and then I noticed what I had missed at first sight: that even though the data was there, it was all mangled.
>> I18n.backend
=> #<I18n::Backend::Simple:0x7f74643e2f08 @skip_syntax_deprecation=false, @translations={:"\357\273\277# Sample localization file for English. Add mor
e files in this directory for other locales. # See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.\nen"=>{:Dest
roy=>"Remove", :suspend=>"suspend", :confirm=>"Are you sure?", :Admin=>"Administration", :suspended=>"%{model} was successfully suspended.", :Back=>"B
ack", :updated=>"%{model} was successfully updated.", :html_title=>"DeficitPuzzle", :to_frontpage=>"to frontpage", :approve=>"approve", :Show=>"Show",
:to_admin=>"to administration", :theme=>{:n=>{:one=>"1 theme", :other=>"%{count} themes"}, :List=>"Listing themes", :New=>"New theme", :Destroy_perma
nently=>"Permanently remove this theme", :Editing=>"Editing theme", :_=>"Theme"}, :Progress=>"Progress", :Proposals=>"Proposals", :approved=>"%{model}
was successfully approved.", :activerecord=>nil, :save_errors=>{:one=>"1 error prohibited this item from being saved", :other=>"%{count} errors prohi
bited this item from being saved"}, :proposal=>{:n=>{:one=>"1 proposal", :other=>"%{count} proposals"}, :List=>"Listing proposals", :New=>"New proposa
l", :Impact=>"Impact", :Destroy_permanently=>"Permanently remove this proposal.", :Editing=>"Editing proposal", :Approved=>"Approved", :"Approved?"=>"
Approved?", :_=>"Proposal", :Title=>"Title", :Description=>"Description"}, :helpers=>{:submit=>nil}, :created=>"%{model} was successfully created.", :
Edit=>"Edit", :title=>"Deficit puzzle: you fix the budget"}, :pt=>{:Destroy=>"Remover", :suspend=>"suspender", :confirm=>"De certeza?", :Admin=>"Ad
ministração", :suspended=>"%{model} foi suspendida com sucesso.", :Back=>"Atrás", :updated=>"%{model} foi actualizada com sucesso.", :html_title=>"
DeficitPuzzle", :to_frontpage=>"ir para página principal", :approve=>"aprovar", :Show=>"Mostrar", :to_admin=>"ir para administração", :theme=>{:n=>
{:one=>"1 tema", :other=>"%{count} temas"}, :List=>"Listando temas", :New=>"Novo tema", :Destroy_permanently=>"Remover este tema permanentemente.", :E
diting=>"Editando tema", :_=>"Tema"}, :Progress=>"Progressão", :Proposals=>"Propostas", :approved=>"%{model} foi aprovada com sucesso.", :activerecor
d=>{:attributes=>{:theme=>{:title=>"Título"}, :proposal=>{:impact=>"Impacto", :description=>"Descrição", :title=>"Título"}}, :models=>{:theme=>"Te
ma", :proposal=>"Proposta"}}, :save_errors=>{:one=>"1 erro impediu este item de ser salvo", :other=>"%{count} erros impediram este item de ser salvo"}
, :proposal=>{:n=>{:one=>"1 proposta", :other=>"%{count} propostas"}, :List=>"Listando propostas", :New=>"Nova proposta", :Impact=>"Impacto", :Destroy
_permanently=>"Remover permanentemente esta proposta.", :Editing=>"Editando proposta", :Approved=>"Aprovada", :"Approved?"=>"Aprovada?", :_=>"Proposta
", :Title=>"Título", :Description=>"Descrição"}, :helpers=>{:submit=>{:update=>"Actualizar %{model}", :create=>"Criar %{model}"}}, :created=>"%{mod
el} foi criada com sucesso.", :Edit=>"Editar", :title=>"Deficit puzzle: tu consertas o orçamento"}, :en=>{:support=>{:array=>{:words_connector=>", ",
:two_words_connector=>" and ", :last_word_connector=>", and "}}, :number=>{:precision=>{:format=>{:delimiter=>""}}, :format=>{:separator=>".", :delim
iter=>",", :precision=>3, :significant=>false, :strip_insignificant_zeros=>false}, :human=>{:storage_units=>{:units=>{:byte=>{:one=>"Byte", :other=>"B
ytes"}, :kb=>"KB", :mb=>"MB", :gb=>"GB", :tb=>"TB"}, :format=>"%n %u"}, :format=>{:delimiter=>"", :precision=>3, :significant=>true, :strip_insignific
ant_zeros=>true}, :decimal_units=>{:units=>{:million=>"Million", :unit=>"", :billion=>"Billion", :trillion=>"Trillion", :quadrillion=>"Quadrillion", :
thousand=>"Thousand"}, :format=>"%n %u"}}, :percentage=>{:format=>{:delimiter=>""}}, :currency=>{:format=>{:separator=>".", :unit=>"$", :delimiter=>",
", :precision=>2, :significant=>false, :strip_insignificant_zeros=>false, :format=>"%u%n"}}}, :datetime=>{:distance_in_words=>{:about_x_hours=>{:one=>
"about 1 hour", :other=>"about %{count} hours"}, :about_x_years=>{:one=>"about 1 year", :other=>"about %{count} years"}, :x_days=>{:one=>"1 day", :oth
er=>"%{count} days"}, :over_x_years=>{:one=>"over 1 year", :other=>"over %{count} years"}, :less_than_x_minutes=>{:one=>"less than a minute", :other=>
"less than %{count} minutes"}, :about_x_months=>{:one=>"about 1 month", :other=>"about %{count} months"}, :x_minutes=>{:one=>"1 minute", :other=>"%{co
unt} minutes"}, :almost_x_years=>{:one=>"almost 1 year", :other=>"almost %{count} years"}, :x_months=>{:one=>"1 month", :other=>"%{count} months"}, :l
ess_than_x_seconds=>{:one=>"less than 1 second", :other=>"less than %{count} seconds"}, :half_a_minute=>"half a minute", :x_seconds=>{:one=>"1 second"
, :other=>"%{count} seconds"}}, :prompts=>{:day=>"Day", :minute=>"Minute", :month=>"Month", :year=>"Year", :hour=>"Hour", :second=>"Seconds"}}, :time=
>{:formats=>{:default=>"%a, %d %b %Y %H:%M:%S %z", :short=>"%d %b %H:%M", :long=>"%B %d, %Y %H:%M"}, :pm=>"pm", :am=>"am"}, :date=>{:formats=>{:defaul
t=>"%Y-%m-%d", :short=>"%b %d", :long=>"%B %d, %Y"}, :abbr_day_names=>["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], :order=>[:year, :month, :day]
, :day_names=>["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], :abbr_month_names=>[nil, "Jan", "Feb", "Mar", "Apr", "Ma
y", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], :month_names=>[nil, "January", "February", "March", "April", "May", "June", "July", "August", "S
eptember", "October", "November", "December"]}, :errors=>{:format=>"%{attribute} %{message}", :messages=>{:even=>"must be even", :confirmation=>"doesn
't match confirmation", :greater_than_or_equal_to=>"must be greater than or equal to %{count}", :accepted=>"must be accepted", :equal_to=>"must be equ
al to %{count}", :not_an_integer=>"must be an integer", :empty=>"can't be empty", :wrong_length=>"is the wrong length (should be %{count} characters)"
, :less_than=>"must be less than %{count}", :blank=>"can't be blank", :too_short=>"is too short (minimum is %{count} characters)", :exclusion=>"is res
erved", :inclusion=>"is not included in the list", :less_than_or_equal_to=>"must be less than or equal to %{count}", :not_a_number=>"is not a number",
:too_long=>"is too long (maximum is %{count} characters)", :invalid=>"is invalid", :odd=>"must be odd", :greater_than=>"must be greater than %{count}
"}}, :activerecord=>{:errors=>{:messages=>{:record_invalid=>"Validation failed: %{errors}", :taken=>"has already been taken"}}}, :helpers=>{:submit=>{
:submit=>"Save %{model}", :update=>"Update %{model}", :create=>"Create %{model}"}, :select=>{:prompt=>"Please select"}}}}, @initialized=true>