Han*_*sCz 3 named-scope ruby-on-rails internationalization
我想在站点用户编辑/创建页面中进行语言选择下拉列表.
为此,我当然将网站翻译成多种语言.使用I18n.available_languages,我可以得到一个区域代码数组,就像这样
development environment (Rails 2.3.4)
> I18n.available_locales
=> [:en, :da]
Run Code Online (Sandbox Code Playgroud)
此外,我创建了一个语言模型并将其与用户相关联:
# app/models/language.rb
class Language < ActiveRecord::Base
has_many :users
end
# app/models/user.rb
class User < ActiveRecord::Base
belongs_to :language
end
# db/schema.rb
create_table "languages", :force => true do |t|
t.string "name"
t.string "code"
end
create_table "users", :force => true do |t|
t.integer "language_id"
end
Run Code Online (Sandbox Code Playgroud)
然后语言表包含本地语言中的语言环境代码和语言名称,如下所示:
| id | name | code |
------------------------------------
| 28 | Dansk | da |
| 29 | Nederlands | nl |
| 30 | English | en |
| 31 | Esperanto | eo |
Run Code Online (Sandbox Code Playgroud)
然后,我在User new,create和edit操作中进行以下分配:
# app/controllers/users_controller.rb (extract)
@available_languages = I18n.available_locales.collect {|language_code| Language.find_by_code(language_code.to_s)}
Run Code Online (Sandbox Code Playgroud)
我在视图中使用它('available_languages'是一个局部变量,因为来自控制器的@available_languages已传递给部分):
# app/views/users/_form.haml (extract)
= f.collection_select(:language_id, available_languages, :id, :name, {:prompt => true})
Run Code Online (Sandbox Code Playgroud)
所有这些的结果是,用户将获得区域设置选择下拉列表来定义给定用户的区域设置.
我的问题是:是否有一种干净的方法将@available_languages赋值移出UsersController并进入语言模型,所以我可以缩短它:
@available_languages = I18n.available_locales.collect {|language_code| Language.find_by_code(language_code.to_s)}
Run Code Online (Sandbox Code Playgroud)
这样的事情:
@available_languages = Language.translations_available
Run Code Online (Sandbox Code Playgroud)
dwa*_*mac 13
我为每个yml添加了一个"locale_name"键,它的语言名称也是自己的语言.例如:
在es-AR.yml
es-AR:
locale_name: "Castellano"
Run Code Online (Sandbox Code Playgroud)
在en.yml
en:
locale_name: "English"
Run Code Online (Sandbox Code Playgroud)
小智 13
根据Dwaynemac的解决方案,这是一个更完整的答案:
将具有区域设置名称的密钥添加到每个yml文件.例如在en.yml中:
en:
language: English
Run Code Online (Sandbox Code Playgroud)
并在es.yml:
es:
language: Español
Run Code Online (Sandbox Code Playgroud)添加一个帮助器方法(例如在/app/helpers/application_helper.rb中),该方法创建一个区域设置和区域设置名称对的数组:
def locale_name_pairs
I18n.available_locales.map do |locale|
[I18n.t('language', locale: locale), locale.to_s]
end
end
Run Code Online (Sandbox Code Playgroud)在您的表单中用于locale_name_pairs创建您的选择下拉列表:
f.select :locale, options_for_select(locale_name_pairs, @user.locale)
Run Code Online (Sandbox Code Playgroud)注意懒惰:如果您希望跳过步骤2,则可以在步骤3中使用以下单行:
f.select :locale, options_for_select(I18n.available_locales.map{ |locale| [I18n.t('language', locale: locale), locale.to_s] } , @user.locale)
在我看来,你正在做一些有趣的事情。首先存在以下问题:
I18n.available_locales.collect {|language_code| Language.find_by_code(language_code.to_s)}
Run Code Online (Sandbox Code Playgroud)
此设置使您为每个可用的语言环境生成一个 SQL 查询。此外,如果每个语言环境I18n.available_locales都有一个对应的Language对象,反之亦然,这段代码似乎有点不必要。你也可以这样做:
Language.find(:all) # or even Language.all
Run Code Online (Sandbox Code Playgroud)
如果由于某种原因,它们不直接映射,您可以使用它:
Language.all(:conditions => { :code => I18n.available_locales })
Run Code Online (Sandbox Code Playgroud)
更详细的形式相当于:
Language.find(:all, :conditions => ["code IN (?)", I18n.available_locales])
Run Code Online (Sandbox Code Playgroud)
这将找到其代码在 I18n.available_locales 中列出的所有语言。如果你想要这个方法的快捷方式,你可以使用named_scopes:
class Language < ActiveRecord::Base
has_many :users
named_scope :translation_available, :conditions => { :code => I18n.available_locales }
end
Run Code Online (Sandbox Code Playgroud)
有了这个,你可以调用:
Language.translation_available
Run Code Online (Sandbox Code Playgroud)
我想这就是你想要的。
| 归档时间: |
|
| 查看次数: |
6944 次 |
| 最近记录: |