2017-07-27 82 views
4

如果某个资源未获得授权,CanCanCan会显示本地化的Flash消息。CanCanCan在哪里可以定义flash“%{subject}”,以及如何修改以符合Rails本地化约定?

https://github.com/CanCanCommunity/cancancan/wiki/Translations-(i18n)

# en.yml 
en: 
    unauthorized: 
    manage: 
     all: "You do not have access to %{action} %{subject}!" 

我已经通过GitHub库挖了,但我不能找出subject变量是如何定义的。

从输出中,我猜想subject被定义为类似object.class.name.underscore的东西。

我想改变它以使用object.model_name.human

这将使它与Rails约定更加一致,并且更易于本地化。

en: 
    activerecord: 
    models: 
     mymodel: MyLocalizedSubjectName 

有人点我定义subject代码,还是建议我怎么能修补CanCanCan使用本地化模型的名字呢?

回答

2

它在我看来像消息来自the unauthorized_message method in ability.rb。特别是,这些行:

variables[:subject] = (subject.class == Class ? subject : subject.class).to_s.underscore.humanize.downcase 
    message = I18n.translate(keys.shift, variables.merge(scope: :unauthorized, default: keys + [''])) 

所以,你可以重新定义方法做你想做的(虽然它已经在使用humanize)。

编辑:包括使用human和命名空间模型时关于i18n键的注释。由于语言环境的文件是这样的:

en: 
    activerecord: 
    models: 
     user: xxxx 
     base: aaaa 
     activerecord/base: bbbb 
     active_record/base: cccc 

我得到这些结果:

2.4.1 :001 > User.model_name.human 
=> "xxxx" 
2.4.1 :002 > ActiveRecord::Base.model_name.human 
=> "cccc" 
2.4.1 :003 > 

你也可以说ActiveRecord::Base.model_name.i18n_key避免一些试验和错误。

+0

谢谢@paul。我的问题是,使用'underscore'的当前实现不支持命名空间类。例如,如果subject是一个'Namespace :: Model',那么这个方法返回与'humanize'或Rails语言环境文件不兼容的'namespace/model'。我正在考虑修补此方法,并用'subject.model_name.param_key.humanize'替换'subject.class.to_s.underscore.humanize'。这听起来合理吗?还是我错过了CanCanCan实现的明显特点? –

+0

对不起,我的意思是'subject.model_name.human' –

+1

听起来对我来说很合理!我确定内联条件是有原因的,所以我会说:'variables [:subject] =(subject.class == Class?subject:subject.class).model_name.human'。例如'ActiveRecord :: Base.model_name.human'只给出''Base''。 –

0

根据CanCanCan documentation for authorize method可以提供这样的自定义消息:

authorize! :edit, @widget, message: I18n.t :all, scope: [: unauthorized, :manage], action: :edit, subject: Item 

变量根据Documentation of I18n for Rails

+0

感谢@igor,但我真的在寻找一个通用的解决方案。我想知道如何强制使用已在应用程序中定义的本地化模型名称。 –

0

您可以通过在YML文件中指定它覆盖您的信息传递。你的情况:

en: 
    unauthorized: 
    edit: 
     widget: "You do not have access to edit item!" 
如果你想在所有你可以尝试的情况下改变控件的名称

en: 
    unauthorized: 
    manage: 
     widget: "You do not have access to %{action} item!" 

你有最后的选择是简单地覆盖你的Widget类to_s方法:

class Widget 
    def self.to_s 
    'Item' 
    end 
end 
+0

感谢@coorasse,但不是一一定义每个模型,我真的在寻找一个通用的解决方案。我的应用程序的模型名已经按照Rails惯例进行了本地化,我试图弄清楚如何使用这些值来强制使用'%{subject}'。 –

0

本地化位于文件夹路径config/locale中,如果您只是想更改默认消息,您应该在这里找到您要查找的内容。 否则,如果您想更改语言或具有多种语言,则可以在config/application上设置它。RB通过设置,为例子:

I18n.available_locales = [:en, :it] 
config.i18n.default_locale = :it 

第一线做出语言,默认的是en.yml但你可以有更多的取决于你所安装的宝石。例如,我设计了四个文件:en.yml,it.yml,devise.en.yml和devise.it.yml。 要提供一种语言,请确保每个文件都有重复。 如果你想从一个由控制器,你可以通过切换到另一个应用程序中的:

I18n.locale = :it 
I18n.locale = :en 

,或者如果你想控制你可以通过设置一个默认:

I18n.locale = I18n.default_locale 

希望我可能会有帮助,再见

+0

谢谢@Pietro。不幸的是,如果底层模型是命名空间的,CanCanCan生成的Flash看起来与Rails的'config/locale'文件不兼容。也许我忽略了一些明显的东西? –

相关问题