رابط القضبان بالصفحة الحالية وتمرير المعلمات إليها

StackOverflow https://stackoverflow.com/questions/2543576

سؤال

أقوم بإضافة i18n إلى تطبيق Rails الخاص بي عن طريق تمرير اللغة باستخدام معاملات URL. عناوين URL الخاصة بي تبدو مثل http://example.com/en/users و http://example.com/ar/users (للجان الإنجليزية والعربية على التوالي).

في ملف مساراتي ، قمت بتعريف طرقي باستخدام خيار: path_prefix:

map.resources :users, :path_prefix => '/:locale'

ويجري ضبط اللغة باستخدام repered_filter محدد في ApplicationController

def set_locale
    I18n.locale = params[:locale]
end

لقد حددت أيضًا ApplicationController#default_url_options ، لإضافة لغة إلى جميع عناوين URL التي تم إنشاؤها بواسطة التطبيق:

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

ما أريده هو إضافة رابط في رأس التخطيط (المعروض في جميع الصفحات) من شأنه أن يرتبط بنفس الصفحة ولكن مع اللغة الأخرى.

على سبيل المثال ، إذا كنت أتصفح اللغة العربية ، فأنا أريد رابط "الإنجليزية" في الرأس ، وسيعيدني إلى صفحتي الحالية ، وتعيين اللغة إلى اللغة الإنجليزية. هل هناك طريقة للقيام بذلك في القضبان؟

هل كانت مفيدة؟

المحلول

استغرق مني بعض الوقت للعثور على هذا ولكن هنا الحل الخاص بي:

link_to 'English', url_for( :locale => 'en' )
link_to 'Deutch', url_for( :locale => 'de' ) 

من المستندات هنا: http://api.rubyonrails.org/classes/actionController/base.html#m000649

عند إنشاء عنوان URL جديد ، قد يتم ملء القيم المفقودة من معلمات الطلب الحالي. على سبيل المثال ، سيحتفظ url_for: Action => 'Some_Action "بوحدة التحكم الحالية ، كما هو متوقع. يمتد هذا السلوك إلى معلمات أخرى ، بما في ذلك: وحدة التحكم ،: معرف ، وأي معلمات أخرى يتم وضعها في مسار المسار.

لذا فإن استخدام url_for سيؤدي إلى افتراضي إلى معلمات الطلب الحالي ، فقط قم بتغيير الكود الذي تريده في الكود الخاص بك. في هذه الحالة ، كان كل ما قمت بتغييره: لغة ، لذلك يبقى كل شيء آخر كما هو.

لاحظ أن هذا يعمل أيضًا لـ "Hidden": المعلمات. لذلك إذا كان لديك:

map.my_map ':locale/my_map', :controller => 'home', :action => 'my_map'

باستخدام url_for أعلاه في الصفحة/en/my_map لن يكون له "المنزل" في عنوان URL (أي/en/home/my_map). علاوة.

نصائح أخرى

لذلك وجدت طريقة للقيام بذلك بشكل أكثر صراحة دون الاعتماد على السحر (بقدر).

url_for(params.merge({:your_new_parameter => value}))

هذا يجب أن يعمل في أي link_to.

كل ما يفعله هو أخذ معلمات الطلب الحالي ودمج التجزئة الجديدة المطلوبة فيها ثم إنشاء عنوان URL جديد لذلك.

ارتباط بالصفحة الحالية مع أماكن مختلفة

تم اختباره على القضبان 4

اهلا جميعا. بعد بعض الوقت من البحث ، قررت أن أكتب حلي لهذا الغرض.

link_to 'English', url_for( :locale => 'en' )
link_to 'Deutch', url_for( :locale => 'de' ) 

هذا يعمل بشكل مثالي ، لكنه يسمح الضعف XSS مجرد تمرير المعلمات في عنوان URL الخاص بك كما هو موضح أدناه:

http://localhost:3000/en/about?host=www.fishingsiteorbadurl.com/%23&port=80

أو أسوأ حالة:

http://localhost:3000/en/about?host=%D0%BE%D1%87%D0%B5%D0%BD%D1%8C%D0%BF%D0%BB%D0%BE%D1%85%D0%BE%D0%B9%D1%81%D0%B0%D0%B9%D1%82.%D1%80%D1%84

تحقق من عناوين URL التي ستحصل عليها بعد مرور هذا الرابط في طلبك.

حل الإنتاج الخاص بي.تعيد طريقة "تغيير اللغة" إلى أي صفحة مع لغة مناسبة فقط باستخدام http_referer في كائن الطلب.يرجى ملاحظة: طريقة uri.path للحصول على مسار فقط ، وليس عنوان URL الكامل

جعل طريقة "تغيير لغة" في أي وحدة تحكم:

        def change_lang

        if request.referer.nil?
                 refer = root_url
        else
                 uri = URI(request.referer)
                 refer = uri.path
        end
        lang = params[:lang]
        cookies[:locale] = lang
        redirect_to refer

        end

application_controller.rb

before_action :set_locale

def set_locale

# -- Get lang from cookies or url parameter locale

user_locale = cookies[:locale] || params[:locale]

# -- If present

if user_locale.present? 

    # -- If it is has 2 symbols

    user_locale = user_locale.scan(/[a-zA-Z]{2}/) 
else

    # -- If no - use default en locale

    user_locale = 'en'
end


# -- Check, is this locale available for using.
# Please note: this needed for disable invalid locale warning.

if I18n.available_locales.include?(user_locale[0].to_sym)

    I18n.locale =  user_locale[0]
else
    I18n.locale =   "en"
end

end

أضف هذا إلى تخطيطك

<%= link_to 'English', change_lang_path('en') %> <%= link_to 'Russian', change_lang_path('ru') %>

config/routes.rb

scope "(:locale)", locale: /[a-zA-Z]{2}/ do
get "change_lang/:lang" => "users#change_lang", :as => "change_lang"
end

ليست هناك حاجة لاستخدام params.merge أو أي حل قرد.

آمل أن يساعد هذا ، لأنني شخصياً أمضيت الكثير من الوقت لحلها.

يمكنك تحليل request_uri واستبدال موقعك في المسار بتعبير منتظم

حسنًا ، هنا مثال مساعد. إذا فهمت الهدف بشكل صحيح

def locale_url(url, locale)
  url.gsub(/\/\w*$/, "/#{locale}")
end

url = "http://www.domain.com/products/1/ru" # or request.request_uri
locale = "en"
locale_url(url, locale) #=> "http://www.domain.com/products/1/en"

هذه نقطة بداية ، بحيث يمكنك عمل بعض الأشياء المختلفة التي تحتاجها

ألقِ نظرة على هذا ، على الرغم من أنه قد لا يكون جافًا وسليمًا ، ولكنه يعمل تمامًا بالنسبة لي. يقرأ جميع المعلمات التي قمت بتزويدها باستبدال عناوين URL EX فقط: http://example.com:3000/us/users؟t=123&m=343 إلخ

  def us_link           
        link_to "US", form_locale_url("/us")            
  end

  def jp_link           
    link_to "Japan",form_locale_url("/jp")           
  end              

  def form_locale_url(locale)            
    new_url = request.request_uri          
    new_locale_url = new_us_url = new_jp_url = new_url           
    if new_url == "/"          
      new_locale_url.sub!(/\//,locale)           
    elsif (new_url =~/\/us/) == 0        
      new_us_url.sub!(/\/us/,locale)        
    elsif (new_url =~/\/jp/) == 0          
      new_jp_url.sub!(/\/jp/,locale)       
    end     
  end

شارع أسرع بكثير - ومريح إذا كان لديك العديد من المعلمات التي تتغير في أماكن مختلفة ... تجنب الفوضى مع علامة مرساة تدمج فقط المعلمة المحلية الجديدة على تلك الموجودة (وتقتل بالفعل المعامل المحلي القديم).

<%= link_to "ру", request.params.merge( locale: 'ru' ) %>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top