Rails globalize + friendly id
Asked Answered
H

1

2

I have a problem with globalize and friendly_id. The site has 2 languages Ru and En. Gem friendly_id, globalize and friendly_id-globalize configured and work. If I change the language from Russian to English, all is well:

http://127.0.0.1:3000/ru/o-saite -> http://127.0.0.1:3000/en/about-site

But when I change from English to Russian going wrong redirection:

http://127.0.0.1:3000/en/about-site -> http://127.0.0.1:3000/ru/about-site

page model:

class Page < ActiveRecord::Base
  validates :title, :content, :slug, presence: true
  validates :slug, uniqueness: true
  validates :title, length: { minimum: 3, maximum: 255 }
  validates :content, length: { minimum: 5 }

  # globalize
  translates :title, :content, :slug

  # FriendlyId
  extend FriendlyId

  friendly_id :slug_candidates, use: [:slugged, :finders, :globalize]

  def slug_candidates
    [
      :title,
      [:title, :id]
    ]
  end

  def should_generate_new_friendly_id?
    title_changed?
  end

  def normalize_friendly_id(string)
    title.to_s.to_slug.normalize(transliterations: :russian).to_s
  end

end

migration:

class TranslatePage < ActiveRecord::Migration
  def self.up
    Page.create_translation_table!({
      title: :string,
      content: :text,
      slug: :string
    }, {
      migrate_data: true
    })
  end

  def self.down
    Page.drop_translation_table! migrate_data: true
  end

end

from application.rb

config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')]
config.i18n.default_locale = :ru
config.i18n.fallbacks = true

page controller

class PagesController < ApplicationController

  before_action :load_page, only: [:show]

  def show    
  end

  private
    def load_page
      @page = Page.friendly.find(params[:id])
      redirect_to action: action_name, id: @page.friendly_id, status: 301 unless @page.friendly_id == params[:id]
    end

    def page_params
      params.require(:page).permit(:title, :content,:slug, :published)
    end

end

what could be the problem?

SOLVED?

Problem was in the views. In layouts/aplication.html.slim was:

ul class='change_lang'
 li = link_to_unless I18n.locale == :en, "EN", locale: :en
 li = link_to_unless I18n.locale == :ru, "RU", locale: :ru

Now in pages/show.slim

- content_for :change_lang do
  li
    - link = I18n.with_locale(:ru){page_path(@page, locale: 'ru')}
    = link_to 'RU', link
  li
    - link = I18n.with_locale(:en){page_path(@page, locale: 'en')}
    = link_to 'EN', link

In layouts/aplication.html.slim

ul class='change_lang'
  - if content_for?(:change_lang)
    = yield :change_lang
  - else
    li = link_to_unless I18n.locale == :en, "EN", locale: :en
    li = link_to_unless I18n.locale == :ru, "RU", locale: :ru

https://github.com/norman/friendly_id-globalize/issues/7

There are more minimalistic approach. But this method server is hung.

Heeley answered 19/1, 2016 at 13:52 Comment(8)
I think the redirect is in your controller, right? Can you include it?Silesia
Hi, MichalI. I add controller in post.Heeley
So if you open Rails console and do I18n.locale=:ru; Page.first.friendly_id you get name in Russian but for I18n.locale=:en; Page.first.friendly_id in English, right?Silesia
>> I18n.locale=:ru; Page.first.friendly_id Page Load (0.8ms) SELECT "pages".* FROM "pages" ORDER BY "pages"."id" ASC LIMIT 1 Page::Translation Load (0.4ms) SELECT "page_translations".* FROM "page_translations" WHERE "page_translations"."page_id" = $1 [["page_id", 1]] => "o-saite" Heeley
>>I18n.locale=:en; Page.first.friendly_id Page Load (0.9ms) SELECT "pages".* FROM "pages" ORDER BY "pages"."id" ASC LIMIT 1 Page::Translation Load (0.5ms) SELECT "page_translations".* FROM "page_translations" WHERE "page_translations"."page_id" = $1 [["page_id", 1]] => "about-site" Heeley
Ok, but friendly_id is not translated according to your model, can you try using @page.slug in your controller?Silesia
I think yes. which can be a problem when using @page.slug in controller?Heeley
No idea, but it's worth trying!Silesia
P
0

i've a generic answer. please let me now if it works for you. if you have a namespace you can set up in :shop, if not just url_for(obj)

in your application_helper.rb

def languages(obj=nil)
    content_for(:switch_locale) do
      I18n.available_locales.each do |locale|
        I18n.with_locale(locale) do
          concat(
            if obj
             content_tag(:li, (link_to locale, url_for([:shop, obj]) ))
            else
             content_tag(:li, (link_to locale, url_for(locale: locale.to_s) ))
            end              
          )
        end
      end
    end
  end

in your views

- languages @category

or simply

- languages

in application.html.(erb/haml.slim) or wherever you want to render the translations. =yield(:switch_locale)

Provision answered 22/1, 2017 at 7:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.