Rails3 Facebook-esque localized language picklist - localization

Other than copying Facebook's SELECT and OPTION elements, is there a Rails-native way of generating a Facebook-esque, localized-language select list?

If by "Rails-native" you mean "provided by Rails core," then no. However, you can access a list of locales your app provides translations for via I18n.available_locales. If one of the values of your locale is a localized version of the name of the language, you can use it to build a select:
# as a helper
def available_locales
I18n.available_locales.map{ |l| [t('name', :locale => l), l] }
end
# in a view
= select_tag :language, options_for_select(available_locales, I18n.locale.to_sym)
If you want something that will build the list for you, you might check out a Gem or plugin, such as localized_language_select.

Related

Fast_Gettext Not Displaying Translations in Rails 3.2.13 Application

I have PO files (en.po & fr.po) that I want to use to localize my Rails application into French. I submitted the question https://stackoverflow.com/questions/17203622/translating-a-rails-application-3-2-13-using-po-gettext-files recently to see if I could get any help. I mentioned that I had read some information about Fast-Gettext and another gem. I decided to look at the Fast-Gettext gem since it allows the use of PO files without using a database.
I added the latest versions of fast_gettext and gettext_i18n_rails in my Gemfile. I installed the latter gem to get rid of an undefined method "_" error message even though I have no plans at this point to use the database feature.
I added the following code in config/application.rb.
# add FastGettext configuration
FastGettext.add_text_domain 'my_app', :path => 'config/locales', :type => :po, :ignore_fuzzy => true, :report_warning => false
FastGettext.default_text_domain = 'my_app' # set the default textdomain
FastGettext.default_available_locales = ["en","fr"] # set available locales # (note: the first one is used as a fallback if you try to set an unavailable locale)
FastGettext.default_locale = 'en'
Here is my setup in application_controller.rb to allow the locale to be set and saved using a cookie.
include FastGettext::Translation
before_filter :set_users_locale
def set_users_locale
I18n.locale = FastGettext.set_locale(params[:locale] || cookies[:locale] ||
request.env['HTTP_ACCEPT_LANGUAGE'] || 'en')
cookies[:locale] = I18n.locale if cookies[:locale] != I18n.locale.to_s
end
I added logic where the user can click a flag and set the value of :locale.
<%= link_to_unless_current image_tag("flag_us_30px.jpg", :alt => "Set Language to English"), locale: "en" %>
<%= link_to_unless_current image_tag("flag_fr_30px.jpg", :alt => "Set Language to French"), locale: "fr" %>
When a person clicks the flag it sets the value of :locale correctly. I have my routes formatted as domain.com/:locale/link. Right now the root will include the locale until I add logic to override it.
Here are two statements in my views that I am testing with:
<%= _("Language") %>
<%= _("Note: If you do not understand the text on the icons, use the text links at the bottom of the page.") %>
When I click the French flag to change the value of :locale to "fr" the link changes properly but the code for both strings remains in English. The PO file has the French translation for both of these terms. I would think that if it had not found the PO files that I should be seeing error messages stating it did not find them.
I first attempted to use the configuration code in config/initializers/fast_gettext.rb but did not get any results so I decided to put it in config/application.rb to see if I could get it to work. I also removed ':ignore_fuzzy => true, :report_warning => false' to see if that may change things. However I get the same results.
I am using fast_gettext because back in 2011 #svenfuchs recommended it for using Gettext. I may try and contact him on Twitter since it looks like that is the only place I can find where he is active these days.
Any help would be appreciated.
Why are you using PO files instead of common Rails translations?
Or the globalize3 if you prefer to save the translations on database and add model translations.
There's also a gem to help you converting your existing translations: i18n-translators-tools.

Ruby on Rails: bbc-code and performance

I am using bb-code in a Rails application for postings and comments. At the moment, I have the following to put a post's content in a view:
<%= #post.content.bbcode_to_html.html_safe.gsub('<a', '<a rel="nofollow"') %>
What is the best way to convert the bb-code to html and add "nofollow" to all links?
Thanks!
The bb-ruby gem you are using allows for using custom BBCode translations passed as parameters to the bbcode_to_html method. However, if you really want ALL links to contain the rel="nofollow", I think your best bet is going to be monkey patching them gem itself. Based on the BBRuby source, you want to do this:
module BBRuby
##tags = ##tags.merge({
'Link' => [
/\[url=(.*?)\](.*?)\[\/url\]/mi,
'\2',
'Hyperlink to somewhere else',
'Maybe try looking on [url=http://google.com]Google[/url]?',
:link],
'Link (Implied)' => [
/\[url\](.*?)\[\/url\]/mi,
'\1',
'Hyperlink (implied)',
"Maybe try looking on [url]http://google.com[/url]",
:link],
'Link (Automatic)' => [
/(\A|\s)((https?:\/\/|www\.)[^\s<]+)/,
' \2',
'Hyperlink (automatic)',
'Maybe try looking on http://www.google.com',
:link]
})
end
This will rewrite the BBRuby translator to always include a nofollow attribute. I would put this in config/initializers with a descriptive filename such as bbruby_nofollow_monkeypatch.rb
As for the html_safe, I would leave that as is. As I understand it that is a preferred way of doing it and in my opinion it keeps your intent clear. The above monkey patch makes the line in your view more readable:
<%= #post.content.bbcode_to_html.html_safe %>

ActiveAdmin - generate link to index, with filter preset?

In an ActiveAdmin page, I would like to include a link to a list of related resources. For example, given that a
Site has_many Sections and,
Section belongs_to a Site (in my ActiveRecord models),
I would like my Site's show page to include a link to Sections within the site, which would go to the Section index page, with the Site filter preset.
Note that
I do not want to use ActiveAdmin's belongs_to function;
I don't want nested resources for a number of reasons (depth of nesting > 2, as well as usability concerns).
What I want is to generate a URL similar to the one ActiveAdmin generates if I first go to the Sections index page and then filter by Site.
The query parameter list generated by ActiveAdmin's filtering feature is pretty crazy; is there a helper method I could use to achieve this goal?
Thanks!
I use this syntax:
link_to "Section", admin_sections_path(q: { site_id_eq: site.id })
I worked out a reasonably satisfactory solution after poking around in meta_search for a bit. Syntax is a bit clunky, but it does the trick.
index do
...
column "Sections" do |site|
link_to "Sections (#{site.sections.count})", :controller => "sections", :action => "index", 'q[site_id_eq]' => "#{site.id}".html_safe
end
end
As jgshurts pointed out, the trick is identifying that q[site_id_eq] query parameter.
However, if you don't like the clunky syntax, you can also just use a path helper:
link_to "Sections (#{site.sections.count})", admin_sections_path('q[site_id_eq]' => site.id)
The UrlHelper#link_to documentation shows additional examples of this.
#auto_link(resource, content = display_name(resource)) ⇒ Object
Automatically links objects to their resource controllers. If the
resource has not been registered, a string representation of the
object is returned.
The default content in the link is returned from
ActiveAdmin::ViewHelpers::DisplayHelper#display_name
You can pass in the content to display
eg: auto_link(#post, "My Link")
ActiveAdmin.register Girl do
index do
selectable_column
column :name do |girl|
auto_link(girl, girl.name)
end
column :email
column :created_at
actions
end
Useful-link: http://www.rubydoc.info/github/gregbell/active_admin/ActiveAdmin/ViewHelpers/AutoLinkHelper
Note: This is tested with ActiveAdmin (v1.1.0 and 2.0.0.alpha)
Hope this works with other version as well. Please update this answer if you are sure it works with other versions you know.

How best to DRY will_paginate options

I have 8 controllers using will_paginate to paginate their index pages. I'd like to override the defaults for "Previous" and "Next" on each without having to specify the same options 8 times. Is there a way to override the defaults only once (perhaps by subclassing will_paginate).
will_paginate uses I18n so you can just use that.
Given you use English as the default locale the following line should be present in application.rb:
config.i18n.default_locale = :en
you can then change the text of the pagination links by adding the following to config/locales/will_paginate.en.yml:
en:
will_paginate:
previous_label: "← go back"
next_label: "go forward →"
Alternatively you can add them to your default translations file: config/locales/en.yml
but I have found that it quickly becomes to large to handle.
Note: If you use another locale, for instance es, for this to work you need to at least replace the en: keys within the YAML files to es: and to be concise about naming your files,
use either config/locales/will_paginate.es.yml or config/locales/es.yml.
I'm assuming you're doing something like this in your controllers:
will_paginate #collection, :previous_label => '< go back', :next_label => 'go forward >'
Your problem is that you want to use these labels everywhere in your application, so it's pointless to repeat them. In that case, you could define a helper like this:
def paginate(collection, options = {})
defaults = {
:previous_label => '< go back',
:next_label => 'go forward >',
}
options = defaults.merge(options)
will_paginate collection, options
end
After that, calling paginate #collection in your views will use your defaults and still let you override them if necessary.
EDIT: suweller's response is definitely the better way to go in this case, especially considering it's approved by mislav, the plugin creator :). I'd completely forgotten about the translation file option. My solution could probably be useful in the general case, when the helper is not configurable in a similar way.

Rails / I18n: default scope

I'm using the default I18n module for Rails to translate my strings in views.
<%= t("registration.heading") %>
Now, when I'm in the registration-view, all my strings start with registration. I always have to write
<%= t("registration.heading.notice") %>
// or
<%= t(:heading, :scope => :registration) %>
It would be nice to define a default scope for that file (maybe even in the controller), so a call to t automatically adds the defined scope
// controller
set_i18n_default_scope :registration
// view
<%= t(:heading) %>
// --> looks in "registration.heading"
Is this possible?
If you organize your translations adding a view name, as in:
en:
registration:
index:
heading: "Registration heading"
then you may use this:
<%= t(".heading") %>
Notice that the first character is a dot.
You may read about it in Rails Internationalization (I18n) API Guide
If you have texts which are shared amongst numerous views, and you don't want to copy the same translation in each section for each view, you may use YAML references. They are nicely described on wikipedia: http://en.wikipedia.org/wiki/YAML#Repeated_nodes
It is possible. Check section 4.1.4 of the Rails i18n API
4.1.4 “Lazy” Lookup
Rails 2.3 implements a convenient way
to look up the locale inside views.
When you have the following
dictionary:
es: books:
index:
title: "Título"
you can look up the books.index.title value inside
app/views/books/index.html.erb
template like this (note the dot):
<%= t '.title' %>
Regarding Lazy Lookups:
Here's the general solution for this kind of problem
Common Problem: Where is Rails trying to look-up L10N / I18N Strings? - e.g. when doing Lazy Lookups
It's not easy to guess, because it's different for Views, Controllers, Models, Labels, Helpers, or Validations... etc... but...
It's easy to find out directly, using this:
http://www.unixgods.org/Rails/where_is_Rails_trying_to_lookup_L10N_strings.html
this helps figuring out what Rails thinks the current scope is (e.g. when using ".heading")
3 Simple Steps:
create a file ./config/initializers/i18n.rb , as described in the article above
put t('.heading') in your view
start "rails server" and look in the console output where Rails thinks the default location is for '.heading' for this view... e.g. what's the I18N-key
(4. then add the I18N string into the location identified by the key)
Works like a charm :-)
If you want to print out keys that I18n gem's lazy mode is looking for, you can add that in a i18n.rb file in your initializers folder:
module I18n
module Backend
class Simple
module Implementation
alias_method :lookup_orig, :lookup
# Give ability to check I18n looked up keys in lazy mode by setting env var I18N_DEBUG to true
#
def lookup(locale, key, scope = [], options = {})
puts "I18N keys: #{I18n.normalize_keys(locale, key, scope, options[:separator])}" if ENV['I18N_DEBUG']
lookup_orig(locale, key, scope, options)
end
end
end
end
end
(Gist: https://gist.github.com/capripot/6e6cf778ad2db0443280)
And then start your server like for instance:
I18N_DEBUG=true bundle exec rails server

Resources