رابط القضبان بالصفحة الحالية وتمرير المعلمات إليها
-
23-09-2019 - |
سؤال
أقوم بإضافة 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' ) %>