将可用语言与语言名称相匹配

发布于 2024-08-06 11:36:15 字数 1764 浏览 3 评论 0原文

我想在网站用户编辑/创建页面中创建语言选择下拉列表。

为此,我当然将该网站翻译成不止一种语言。 使用 I18n.available_languages,我可以获得一个区域设置代码数组,如下所示

development environment (Rails 2.3.4)
> I18n.available_locales
   => [:en, :da]

此外,我创建了一个语言模型并将其与用户相关联:

# 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

然后语言表包含一个区域设置代码和母语的语言名称,如下所示:

| id  | name                | code |
------------------------------------
| 28  | Dansk               | da   |
| 29  | Nederlands          | nl   |
| 30  | English             | en   |
| 31  | Esperanto           | eo   |

然后,我在用户新建、创建和编辑操作中进行以下分配:

# app/controllers/users_controller.rb (extract)
@available_languages = I18n.available_locales.collect {|language_code| Language.find_by_code(language_code.to_s)}

我在视图中使用它,如下所示(“available_languages”是一个局部变量,因为来自控制器的@available_languages已传递给部分):

# app/views/users/_form.haml (extract)
= f.collection_select(:language_id, available_languages, :id, :name, {:prompt => true})

结果最重要的是,用户将获得一个区域设置选择下拉列表来定义给定用户的区域设置。

我的问题是: 有没有一种干净的方法可以将 @available_languages 分配从 UsersController 移出并移入语言模型,以便我可以将其缩短

@available_languages = I18n.available_locales.collect {|language_code| Language.find_by_code(language_code.to_s)}

为这样:

@available_languages = Language.translations_available

I want to make a language selection dropdown in a site user edit/create page.

For this purpose, I have of course translated the site to more than one language.
Using I18n.available_languages, I can then get an array of locale codes, like so

development environment (Rails 2.3.4)
> I18n.available_locales
   => [:en, :da]

Furthermore, I have created a Language model and related it to User:

# 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

The language table then contains a locale code and a language name in the native tongue, like so:

| id  | name                | code |
------------------------------------
| 28  | Dansk               | da   |
| 29  | Nederlands          | nl   |
| 30  | English             | en   |
| 31  | Esperanto           | eo   |

I then have the following assignment in the User new, create and edit actions:

# app/controllers/users_controller.rb (extract)
@available_languages = I18n.available_locales.collect {|language_code| Language.find_by_code(language_code.to_s)}

which I use in the view like so ('available_languages' is a local variable, since @available_languages from the controller has been passed to a partial):

# app/views/users/_form.haml (extract)
= f.collection_select(:language_id, available_languages, :id, :name, {:prompt => true})

The upshot of all this, is that the user will get a locale select dropdown to define the locale for the given user.

My question is:
Is there a clean way to move the @available_languages assignment out of the UsersController and into the Language model, so I can shorten this:

@available_languages = I18n.available_locales.collect {|language_code| Language.find_by_code(language_code.to_s)}

to something like this:

@available_languages = Language.translations_available

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

云雾 2024-08-13 11:36:15

我向每个 yml 添加一个“locale_name”键,并用它自己的语言表示它的语言名称。
例如:

在 es-AR.yml

es-AR:
  locale_name: "Castellano"

中 在 en.yml 中

en:
  locale_name: "English"

I add a "locale_name" key to each yml with it's language name in it's own language as well.
For example:

in es-AR.yml

es-AR:
  locale_name: "Castellano"

in en.yml

en:
  locale_name: "English"
尬尬 2024-08-13 11:36:15

这是基于 Dwaynemac 解决方案的更完整答案:

  1. 将带有区域设置名称的密钥添加到每个 yml 文件中。例如在 en.yml 中:

    <前><代码>en:
    语言: 英语

    在 es.yml 中:

    <前><代码>es:
    语言: 西班牙语

  2. 添加一个帮助器方法(例如在 /app/helpers/application_helper.rb 中),该方法创建区域设置和区域设置名称对的数组:

     def locale_name_pairs
        I18n.available_locales.map |locale|
          [I18n.t('语言', 语言环境: 语言环境), locale.to_s]
        结尾
      结尾
    
  3. 在表单中使用 locale_name_pairs 创建您的选择下拉列表:

    f.select :locale, options_for_select(locale_name_pairs, @user.locale)
    

懒人注意: 如果您想跳过第 2 步,那么您可以使用遵循步骤 3 中的一句话:
f.select :locale, options_for_select(I18n.available_locales.map{ |locale| [I18n.t('语言', locale: locale), locale.to_s] } , @user.locale)

Here's a more complete answer based on Dwaynemac's solution:

  1. Add a key with the locale name to each yml file. For example in en.yml:

    en:
      language: English
    

    and in es.yml:

    es:
      language: Español
    
  2. Add a helper method (for example in /app/helpers/application_helper.rb) which creates an array of locale and locale name pairs:

      def locale_name_pairs
        I18n.available_locales.map do |locale|
          [I18n.t('language', locale: locale), locale.to_s]
        end
      end
    
  3. In your form use locale_name_pairs to create your selection dropdown:

    f.select :locale, options_for_select(locale_name_pairs, @user.locale)
    

Note for the lazy: If you prefer to skip step 2 then you can use the following one-liner in step 3:
f.select :locale, options_for_select(I18n.available_locales.map{ |locale| [I18n.t('language', locale: locale), locale.to_s] } , @user.locale)

可爱暴击 2024-08-13 11:36:15

在我看来,你正在做一些有趣的事情。首先,存在以下一些问题:

I18n.available_locales.collect {|language_code| Language.find_by_code(language_code.to_s)}

此设置会导致您为每个可用区域设置生成一个 SQL 查询。此外,如果 I18n.available_locales 中的每个语言环境都有一个相应的 Language 对象,反之亦然,则此代码似乎有点不必要。您也可以这样做:

Language.find(:all) # or even Language.all

如果由于某种原因,它们没有直接映射,您可以使用它:

Language.all(:conditions => { :code => I18n.available_locales })

更详细的形式相当于:

Language.find(:all, :conditions => ["code IN (?)", I18n.available_locales])

这将找到其代码在 I18n.available_locales 中列出的所有语言。如果你想要这个方法的快捷方式,你可以使用named_scopes:

class Language < ActiveRecord::Base
  has_many :users

  named_scope :translation_available, :conditions => { :code => I18n.available_locales }
end

有了这个,你就可以调用:

Language.translation_available

我想这就是你想要的。

It seems to me that you're doing a couple of funny things. First off there are some problems with the following:

I18n.available_locales.collect {|language_code| Language.find_by_code(language_code.to_s)}

This setup causes you to generate one SQL query for every available locale. Furthermore if every locale in I18n.available_locales has a corresponding Language object and vice-versa, this code seems a bit unnecessary. You might as well just do:

Language.find(:all) # or even Language.all

If for some reason, they don't map directly, you could use this instead:

Language.all(:conditions => { :code => I18n.available_locales })

which in a more verbose form is equivalent to:

Language.find(:all, :conditions => ["code IN (?)", I18n.available_locales])

This will find all languages whose code is listed in I18n.available_locales. If you want a shortcut to this method, you can use named_scopes:

class Language < ActiveRecord::Base
  has_many :users

  named_scope :translation_available, :conditions => { :code => I18n.available_locales }
end

With this, you can then call:

Language.translation_available

I think this is what you wanted.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文