Middleman - Localizing data/yaml files - middleman

How do I go about localizing data string that come from yaml files stored in the data folder
wondered if there were some techniques I have missed for this.

One way i am aware of, is using symbols (pointing to translation items) within your data:
/data/product.yml
title: :product_title
/config.rb
set :lang, :de
activate :i18n, :langs => [:de, :en]
These symbols can be translated as (Middleman) usual ...
/locales/de.yml
---
de:
product_title: "Mein deutscher Produktname"
/locales/en.yml
---
en:
product_title: "My english product title"
... and used in your templates:
/source/localizable/i18n.html.erb
<h1><%= I18n.t(data.product.title) %></h1>
http://0.0.0.0:4567/i18n.html
Mein deutscher Produktname
http://0.0.0.0:4567/en/i18n.html
My english product title

You can use .send method.
In /data/en/production.yml
---
title: "My english product title"
In /data/ja/production.yml
---
title: "私の日本語の商品名"
Then in your template...
<h1><%= I18n.t(data.send(I18n.locale.to_sym).product.title) %></h1>

Related

How to update the database when users download an ActiveStorage blob attachment?

Currently users can download an ActiveStorage blob in my app using the following link:
link_to 'download', rails_blob_path(pj.document.file, disposition: 'attachment')
However, I would like to update an attribute in the database for the associated model to register when the file was first downloaded. This field is called the downloaded_at field.
I have made the following attempt:
Changed the link_to > button_to as I'm updating the model.
Added the appropriate route
Added the following code in the database:
def download
#proofreading_job = ProofreadingJob.find(params[:id])
#proofreading_job.update(downloaded_at: Time.current) if current_user == #proofreading_job.proofreader.user
response.headers["Content-Type"] = #proofreading_job.document.file.content_type
response.headers["Content-Disposition"] = "attachment; #{#proofreading_job.document.file.filename.parameters}"
#proofreading_job.document.file.download do |chunk|
response.stream.write(chunk)
end
ensure
response.stream.close
end
However, this does not do anything except redirect to the #proofreading_job page which is not what I want.
Has anyone done this before and if so how can I accomplish this task.
I think you can also try using your action controller as a proxy, the concept is this:
download the file in your action
check if it is downloaded successfully and other validations
perform clean up operations (in your case the added code in your #3)
send the file back to user using the send_data/send_file rendering method
E.g. in your controller:
def download
file = open(params[:uri])
validate!
cleanup!
send_file file.path
end
Then in your view:
link_to 'download', your_controller_path
Above is just concept and I apologize for only providing pseudo code in advance.
In the end I just used some javascript to capture the click of the button as follows:
td = link_to rails_blob_path(pj.document.file, disposition: 'attachment'),
id: pj.document.id,
download: pj.document.file_name,
class: "btn btn-outline-secondary btn-sm btn-download" do
=pj.document.file_name
i.fa.fa-download.ml-3 aria-hidden="true"
coffee script:
$('.btn-download').on 'click', (e) ->
id = $(this).attr('id')
$.ajax {url: Routes.document_path(id), type: 'PUT'}
routes.rb
resources :documents, only: [:show, :update]
documents_controller.rb:
def update
document = Document.find(params[:id])
authorize([:proofreaders, document])
document.update(downloaded_at: Time.current) if document.downloaded_at.nil?
head :ok
end
This seems to work very well. It updates the database and the user gets the file downloaded to their computer.

Have I found a bug in the Sonos Self-test Suite?

Summary
The Sonos self-test suite seems to incorrectly fail for an item with itemType=other if it also has a custom browse icon.
I believe that the item type other should be included in this list from utility.py:
17 BROWSEABLE_CONTAINER_TYPES = ('artist', 'album', 'genre', 'playlist', 'favorites', 'albumList', 'trackList', 'artistTrackList', 'container', 'favorite', 'collection', 'program', 'show')
Details
When running the sonos self-test suite, I got the following error as part of the output:
...
INFO Start Test Case: 844 Albumart test_custom_browse_icon_configuration
STOP Discovered custom browse icon URI should be something other than None. (is None)
STOP 844 Albumart test_custom_browse_icon_configuration
...
By debugging albumart.py (test_custom_browse_icon_configuration method), I traced the issue to the following extract of the get_sample_custom_browse_icon_url method:
# TODO: Need to drill down one level deeper if the target image url cannot be found on the root level containers
for mediaColl in response.Items:
if mediaColl.itemType in container_types:
if substitution_str in mediaColl.albumArtURI:
return mediaColl.albumArtURI
elif hasattr(mediaColl.albumArtURI,'value') and substitution_str in mediaColl.albumArtURI.value:
return mediaColl.albumArtURI.value
This code was supposed to find containers with custom album art. However, it turns out that container_types was defined by an earlier line:
container_types = [t for t in Validation.BROWSEABLE_CONTAINER_TYPES if t.lower() != 'album']
and Validation.BROWSEABLE_CONTAINER_TYPES was defined in utility.py as follows:
# sonos-selftest/smapi/content_workflow/utility.py
15 class Validation(WorkflowTestFixture, SMAPIClient, SMAPIService):
16
17 BROWSEABLE_CONTAINER_TYPES = ('artist', 'album', 'genre', 'playlist', 'favorites', 'albumList', 'trackList', 'artistTrackList', 'container', 'favorite', 'collection', 'program', 'show')
Note that the type 'other' is missing from this list! I'm pretty sure it is supposed to be inluded in the list, browse.py mentions it:
234 **Reference:** BROWSEABLE_CONTAINER_TYPES = 'artist', 'album', 'genre', 'playlist', 'favorites', 'albumList', 'trackList', 'artistTrackList', 'container', 'favorite', 'collection', 'other', ' program'
Workaround
I was able to work around this issue by changing itemType=other to itemType=container (which are pretty much equivalent).
However, it would be nice if this was fixed in future versions of the Sonos self-test suite.

Pretty Print JSON generated with a jbuilder template in Rails 3.2.8

Anyone have a way to pretty print JSON output from jbuilder?
I can pretty print JSON generated within a controller action with something like:
JSON.pretty_generate(some_json_object)
but once I pass off to a jbuilder template, I'm not aware of a way to have that output pretty printed.
Right now, my action method's render statement is simple:
render formats: :json
And this successfully forces a rendering with jbuilder, regardless of input format type specified (which is my desired behavior).
I found a way to do this:
json_string = render_to_string formats: :json
json_object = JSON.parse(json_string)
render :json => JSON.pretty_generate(json_object)
Again, this assumes there is a jbuilder template for this action, which will create the initial json, which gets rendered to a string, back into a json object and then passed to pretty_generate().
It's a bit circuitous, but it works. I'm of course, totally open to tighter implementations!
# config/initializers/jbuilder_prettify.rb
require "jbuilder"
class Jbuilder
##
# Allows you to set #prettify manually in your .jbuilder files.
# Example:
# json.prettify true
# json.prettify false
#
attr_accessor :prettify
alias_method :_original_target, :target!
##
# A shortcut to enabling prettify.
# Example:
# json.prettify!
#
def prettify!
#prettify = true
end
def target!
#prettify ? ::JSON.pretty_generate(#attributes) : _original_target
end
end
# app/views/api/v1/users/show.json.jbuilder
json.prettify! if %w(1 yes true).include?(params["pretty"])
json.( #user, :id, :name, :created_at, :updated_at )
https://github.com/rails/jbuilder/issues/195#issuecomment-44440569
Expanding on Blake Miller's answer...
Here is the code from the gist:
require 'multi_json'
MultiJson.use :yajl
unless Rails.env.production?
MultiJson.dump_options = {:pretty=>true}
end
I put this into a file called /config/initializers/jbuilder_prettify.rb
In order for this to work you must have the yajl-ruby gem included in your Gemfile. Note that the jbuilder github homepage mentions here how using something like yajl-ruby will speed up your json rendering.
This worked for me, while the accepted answer did not. It's also shorter!
https://gist.github.com/jmoe/02c7476adac24eddd969
require 'multi_json'
MultiJson.use :yajl
unless Rails.env.production?
MultiJson.dump_options = {:pretty=>true}
end
config/initializers/jbuilder.rb with:
class Jbuilder
def target!
::JSON.pretty_generate(#attributes)
end
end
Result, https://localhost:3000/manifest.json
{
"name": "Socializus",
"short_name": "Socializus",
"start_url": "http://localhost:3000",
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
I think this is simpler,
#package = Package.first
json = JSON.parse(#blog.to_json)
PP.pp(json)
{"id_to_s"=>"5222675dbc11149e3a000002",
"title"=>"Package Title",
"version"=>"0.1.1",
"comment"=>
{"user"=>"Joe",
"description"=>"Joe's comment"},
"assets"=>
[{"id_to_s"=>"522a4620fa451436f4000001",
"_type"=>"Illustration",
"start"=>0,
"stop"=>100,
"caption"=>"mountain climbing"},
{"id_to_s"=>"522a56a6fa4514523a000001",
"_type"=>"Illustration",
"start"=>200,
"stop"=>300,
"caption"=>"airport"},
{"id_to_s"=>"522a6a0ffa4514a30e000002",
"_type"=>"Illustration",
"start"=>400,
"stop"=>600,
"caption"=>"doc"},
{"id_to_s"=>"522aa46bbc1114551f000001",
"_type"=>"Illustration",
"start"=>nil,
"stop"=>nil,
"caption"=>nil},
{"id_to_s"=>"522aa47fbc1114551f000002",
"_type"=>"Illustration",
"start"=>10,
"stop"=>30,
"caption"=>"asdflkjsd"}]}
Or, the quicker one-liner,
PP.pp JSON.parse Blog.first.to_json

Rails Mailer multipart + inline images: no html alternative in Apple Mail, TB

Using rails 3.0.10, we need to send mail messages with html and plain text alternative where the html part references images sent along as inline attachments.
The code:
def invite(secure_share)
#share = secure_share
attachments.inline['download.png'] = File.read "#{Rails.root}/public/images/download.png"
mail( :to => secure_share.recipient,
:from => 'dummy#example.com',
) do |format|
format.html { render :layout => 'cargo_secureshare_mailer' }
format.text
end
end
The templates are in place, the inline attachment works and we get a mail with the following structure:
Content-type "multipart/related"
Part "multipart/alternative"
Part "text/html"
Part "text/plain"
Part "image/png" (inline attachment)
Neither Apple Mail nor Thunderbird seem to like this, they will not show the HTML version but only a text version with two "normal" attachments. It seems like the multipart structure is wrong - shouldn't it have "multipart/alternative" as the content type and then "multipart/related" as a wrapper for the html with inline attachments?
Anyone a hint how to fix this?
Found here: http://www.shortround.net/2011/04/07/multipart-alternative-multipart-related-email-with-actionmailer-for-rails-3/
It almost works. i.e. it works for regular attchments but fails for inlined

activeadmin + internationalization

I've updated active_admin to version 0.3.0 to get internationalization working. But I have problems with it.
I have my pl.yml file updated with activeadmin section which looks like this:
pl:
active_admin:
blank_slate:
content: "Nie ma jeszcze rekordów."
link: "Nowy"
dashboard: "Dashboard2"
view: "Podgląd"
This didn't work, so I tried adding this code to my application.rb:
config.before_configuration do
I18n.locale = :pl
I18n.load_path += Dir[Rails.root.join('config', 'locales', '*', '.{rb,yml}')]
I18n.reload!
end
Now internationalization seems to work in development environment, but I still have problems in other environments. I have problem with dashboard: key. Normally, in short, when I18n doesn't find the key it puts key: with capital letter, in this example it would be "Dashboard". But in my case i have something like this:
Develoment:
Production:
Is there anyone who had the same problem? I'm I doing something wrong, or is this an activeadmin bug? Any solution?
I had the same problem. I needed to do this to be able to get it to work in both production and development:
config.before_configuration do
I18n.load_path += Dir[Rails.root.join('config', 'locales', '*.{rb,yml}').to_s]
I18n.locale = :nl
I18n.default_locale = :nl
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '*.{rb,yml}').to_s]
config.i18n.locale = :nl
# bypasses rails bug with i18n in production\
I18n.reload!
config.i18n.reload!
end
config.i18n.locale = :nl
config.i18n.default_locale = :nl
Not very pretty, but probably caused by a bug in Rails.
in application.rb
config.i18n.default_locale = :fr
I18n.locale = config.i18n.locale = config.i18n.default_locale
I18n.reload!
The key reason maybe caused by : Rails chose the locale from enduser's browser, but not your config file. e.g. a Japanese is visiting your website with his browser using English , then your Rails app will show him the "English" text, but not Japanese that you want it to show.
According to Rails i18n document: http://guides.rubyonrails.org/i18n.html, you have to first of all:
edit config/application.rb to set the default_locale
config.i18n.default_locale = :cn
edit your app/controllers/application_controller.rb, to add a before_filter
before_filter :set_locale
# for those user whose browser is not using our default_locale, e.g. a Chinese using English broser,
# just like me. :)
def set_locale
I18n.locale = params[:local] || I18n.default_locale
end
in this case, you should have the "cn" as the default locale.
check your view page, by adding these line of code to any of your page. e.g.
# in products/index.html.erb
<h1>Products List</h1>
default_locale is: <%= I18n.default_locale %> <br/>
current_locale is: <%= I18n.locale %>
the output result should look like:
Products List
default_locale is: cn
current_locale is: cn
and your Rails application should work as you expect.
An alternative that seems to work is creating an initializer with the following:
# config/initializers/i18n_reload.rb
Rails.configuration.after_initialize do
I18n.reload!
end