Skip to content

Instantly share code, notes, and snippets.

@bazzel
Last active March 20, 2022 22:00
Show Gist options
  • Star 21 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save bazzel/ecdff4718962e57c2d5569cf01d332fe to your computer and use it in GitHub Desktop.
Save bazzel/ecdff4718962e57c2d5569cf01d332fe to your computer and use it in GitHub Desktop.
Webpacker and I18n
$ rails new my-i8n --webpack

Gemfile

gem 'i18n-js'
$ bundle --binstubs
$ yarn add i18n-js
$ bin/rails webpacker:install:erb

app/javascript/i18n-js/index.js.erb

import I18n from "i18n-js"
I18n.translations = <%= I18n::JS.filtered_translations.to_json %>;
export default I18n

app/javascript/packs/application.js

import I18n from 'i18n-js/index.js.erb'
console.log(I18n.t('hello'))
$ bin/rails g controller welcome index

config/routes.rb

root 'welcome#index'

app/views/layouts/application.html.erb

<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
$ bin/rails s
@zedtux
Copy link

zedtux commented Jan 19, 2019

Brillant, just perfect !

@capjuancode
Copy link

🥇

@4e4c52
Copy link

4e4c52 commented Mar 4, 2019

Thank you very much!

@joseglego
Copy link

joseglego commented Apr 9, 2019

Hello! @bazzel It works well for me. BUT I have a doubt, why

bundle --binstubs

Why not use the binstub of the specific gem which required it?
Or why it doesn't work with just bundle

@bazzel
Copy link
Author

bazzel commented Jul 12, 2019

Hi @joseglego,

Thanks for the feedback. I'm not sure where I read this, but to my understanding --binstubs creates a /bin directory so commands can be executed as bin/rails s instead of rails s or bundle exec rails s.

@balakirevs
Copy link

balakirevs commented Aug 3, 2019

Hi @bazzel,
In my case all is good, but if I change default locale to something else rather than "en", it still defaults to EN. Any idea what can be wrong?

i have added

application_controller.rb

before_action :set_locale

  def default_url_options(options = {})
    { locale: I18n.locale }.merge options
  end

  def set_locale
    default_locale = Rails.configuration.i18n.default_locale.to_s
    begin
      if params[:locale].to_s.in? MyI8n::LOCALES
        params_locale = params[:locale].to_s
      end
      if request.env['HTTP_ACCEPT_LANGUAGE'].present?
        candidate_locale = request.env['HTTP_ACCEPT_LANGUAGE'].scan(/^[a-z]{2}/).first
        if candidate_locale.to_s.in? MyI8n::LOCALES
          request_locale = candidate_locale.to_s
        end
      end
      @locale = params_locale || session[:locale].presence || request_locale || default_locale
      I18n.locale = @locale.to_s
      session[:locale] = I18n.locale
    rescue
      I18n.locale = default_locale
      session[:locale] = I18n.locale
    end
  end

config/application.rb

module MyI8n
  LOCALES = %w[de fr en].freeze

  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 5.2
    config.i18n.available_locales = MyI8n::LOCALES
    config.i18n.default_locale = 'en'
    config.i18n.fallbacks = (['en'] + MyI8n::LOCALES).uniq
  end
end

routes.rb

scope '(:locale)', locale: /#{I18n.available_locales.join('|')}/ do
    root 'welcome#index'
  end

and also created fr & de yml files.
The result i have always hello world in english in application.js though if i add in the view

<%= I18n.locale %>

and switch locale it shows the correct one.

@hiveer
Copy link

hiveer commented Aug 13, 2019

I have a question here, since webpacker support ERB, why not just use I18n from Rails directly?

@alxckn
Copy link

alxckn commented Aug 25, 2019

I have a question here, since webpacker support ERB, why not just use I18n from Rails directly?

@hiveer ERB asset files will be evaluated at compile time, not upon each request, so the only locale you'll be able to see is the one set as default.

@OtherCroissant
Copy link

How can I make sure webpacker invalidates the cached translations and regenerate the i18n-js/index.js.erb?
When I change the translations that are used in my JS, the translations are not updated in I18n.translations.

@strickland84
Copy link

Ditto @cunknown, @bazzel is there a way to auto-update these without reloading the server when making changes in dev? Thanks for the gist, very helpful

@bazzel
Copy link
Author

bazzel commented Sep 10, 2019

@cunknown @strickland84 don't have an answer for that, I'm afraid. To be honest: I didn't get that far when writing this up, so I think this needs some more investigation.

@kfiltschew
Copy link

kfiltschew commented Sep 18, 2019

If you want to use the rails set locale, you can take this solution:

app/layouts/applcation.html.erb - save default locale in a global variable (LOCALE) you can access everywhere.

...
<script type="text/javascript">
  var LOCALE = "<%= I18n.locale %>";
</script>
...

app/javascript/i18n-js/index.js.erb - use the global variable LOCALE

import I18n from "i18n-js"

I18n.translations = <%= I18n::JS.filtered_translations.to_json %>;
I18n.locale = LOCALE;

export default I18n;

Other points should match the example.

@hadees
Copy link

hadees commented Nov 21, 2019

can you do this without using erb? I'm having other problems with erb and webpacker.

@dev-alihaider
Copy link

Great

@fongfan999
Copy link

Awesome

@Uepsilon
Copy link

👍 thanks man, that saved me at least a few hours.

@nathan-ch
Copy link

nathan-ch commented Sep 29, 2020

Hi, we are changing our front end to use only React as a Single Page Application inside the Rails app with Webpacker.

I wonder if i can use i18n-js to translate html generated from React.
With this piece of code, i am able to receive translations in React code but the js import of I18n only gives defaultLocale, not the currentLocale.
I can write code to get currentLocal from localStorage or cookies easily but is there a way to handle url without rewriting the detection functions in js ?

@t3k4y
Copy link

t3k4y commented Nov 30, 2020

Anyone managed to combine this with jest tests?

@m-andreas
Copy link

m-andreas commented Jul 19, 2021

Thanks for the Hint @kfiltschew! So you can just use:

import I18n from "i18n-js"
I18n.translations = <%= I18n::JS.filtered_translations.to_json %>;
I18n.locale = "<%= I18n.locale %>";
export default I18n

in i18n-js/index.js.erb

@huzaifa-malik
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment