Grape: Response is in wrong locale when 'present' is inside 'I18n.with_locale'

Created on 21 May 2020  Â·  6Comments  Â·  Source: ruby-grape/grape

Not sure if Grape issue, would love to get a direction. Throwing as much details as I can:

Stack is Rails + Grape + Grape Entity + Mobility. I want the response to be rendered in en locale while I18n.default_locale = 'he'. I don't want to change global I18n.locale, but scope it to each request.

My API endpoint looks like

I18n.with_locale('en') do
  present @post, with: V1::Entities::Post::Base
end

post.name is a Mobility translated field, stored as JSON in the db

I stil want to use the block version to scope the locale change to request, but as an experiment I've tried also to set I18n in before and reset in finally, but what I found is I get the response in the locale set in finally. So if I reset it to 'he' — I'll get response in 'he' locale.

I also follow Grape's present method to body and I don't see anything after that. So, I thought, I should see here what is returned in the response.

def body(value = nil)
  if value
    @body = value
  elsif value == false
    @body = ''
    status 204
  else
    instance_variable_defined?(:@body) ? @body : nil
  end
end

And if I print the value from here — it is #<V1::Entities::Post::Base:70259928978620 id=123 name=EnglishName> with proper english value.

I'm confused. It's as if after the present something comes in and changes the locale and the value again to a default locale.

Again, not sure if it's a bug in Grape. Any thoughts\directions would be much appreciated.

needs info

Most helpful comment

@mcfoton We got the same problem in our production :smile:

The solution:

I18n.with_locale(params[:locale]) do
  present post, serializable: true
end

If serializable isn't given, Grape entity only initializes objects inside with_locale then outside of the block the initialized objects get converted to the hash. So, attributes get prepared outside of with_locale :wink:

All 6 comments

@mcfoton Our project uses the same approach and it works I've just checked :wink:

  I18n.with_locale(params[:locale] || I18n.default_locale) do
    present :cities, City.all
  end

However, we don't use Grape Entity there.

@mcfoton I would recommend to create a Rails project where you can reproduce this issue and share with maintainers. Otherwise, I am afraid, the scope is too specific.

@dnesteryuk thank you so much for the prompt reply and for checking things for me.

I've created a demo project, it's standard Rails and two gems: grape and mobility.

localhost:3000/api/posts?locale=en

will respond

{
    "id": null,
    "title": "HE"
}

while expected response would be

{
    "id": null,
    "title": "EN"
}

Please tell if I can provide anything else \ improve on the example.

Did some more tinkering, doesn't seem like a grape bug after all.

localhost:3000/api/posts?locale=en
resource :posts do
      desc 'Return all posts'
      get do
        post = Post.new
        post.title_he = 'HE'
        post.title_en = 'EN'

        I18n.with_locale(params[:locale]) do
          present post
        end
      end
end

results in "title": "HE" (wrong)

while

resource :posts do
      desc 'Return all posts'
      get do
        post = Post.new
        post.title_he = 'HE'
        post.title_en = 'EN'

        Mobility.locale = params[:locale]
        present post
      end
 end

results in "title": "EN" (good)

So it seems that I18n.locale and Mobility.locale have different scope in terms of how they relate to Grape's request context. Any thoughts if that's a bug \ some 'gotcha' to be aware of?

@mcfoton We got the same problem in our production :smile:

The solution:

I18n.with_locale(params[:locale]) do
  present post, serializable: true
end

If serializable isn't given, Grape entity only initializes objects inside with_locale then outside of the block the initialized objects get converted to the hash. So, attributes get prepared outside of with_locale :wink:

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dblock picture dblock  Â·  6Comments

Legogris picture Legogris  Â·  6Comments

davidmccoy picture davidmccoy  Â·  3Comments

hoffm picture hoffm  Â·  5Comments

dblock picture dblock  Â·  7Comments