2011-09-13 13 views
14

मैं एक ऐसे वर्ग पर काम कर रहा हूं जिसका उपयोग दूसरे देशों के कुछ लोगों द्वारा किया जा रहा है। मुझे हर संदेश को स्थानीयकृत करना है, चेतावनी ई.एससी ताकि वे समझ सकें कि हमारा क्या मतलब है। कई मामलों में मैंने अपना लक्ष्य हासिल किया। लेकिन इन गुणों की विशेषताएँ जैसे विवरण गधे में दर्द होता है।सी # में संपत्ति विवरण को स्थानीयकृत कैसे करें?

यहाँ 'क्या मैं अभी है:

[Category("Editable Values"), Description("Sets the minimum select...")] 
    public Ampere Simin 
    { 
     get 
     {...} 
     set 
     {...} 
    } 

और

[Category("Editable Values"), Description(Localisation.Simin)] // "Localisation" here is the internal resource file that i wrote for messages, warnings, exceptions and -unfortunately- descriptions 
     public Ampere Simin 
     { 
      get 
      {...} 
      set 
      {...} 
     } 

है यही कारण है कि मैं क्या करने की कोशिश कर रहा हूँ। लेकिन इस तरह स्थानीयकरण का उपयोग करना संभव नहीं है। किसी चीज के बारे में कोई सुझाव जो मैं इसके बजाय उपयोग कर सकता हूं?

उत्तर

18

उपवर्गों:

[STAThread] 
static void Main() 
{ // just some example code to show it working in winforms, but 
    // anything using System.ComponentModel should see the change 
    Application.EnableVisualStyles();   
    Application.Run(new Form {Controls = {new PropertyGrid {Dock = DockStyle.Fill, SelectedObject = new Foo()}}}); 
} 

class Foo 
{ // assume the following literals are keys, for example to a RESX 
    [LocalizedCategory("cat")] 
    [LocalizedDescription("desc")] 
    [LocalizedDisplayName("disp name")] 
    public string Bar { get; set; } 
} 
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Parameter | AttributeTargets.Delegate | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter)] 
class LocalizedDescriptionAttribute : DescriptionAttribute 
{ 
    static string Localize(string key) 
    { 
     // TODO: lookup from resx, perhaps with cache etc 
     return "Something for " + key; 
    } 
    public LocalizedDescriptionAttribute(string key) 
     : base(Localize(key)) 
    { 
    } 
} 
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event)] 
class LocalizedDisplayNameAttribute : DisplayNameAttribute 
{ 
    static string Localize(string key) 
    { 
     // TODO: lookup from resx, perhaps with cache etc 
     return "Something for " + key; 
    } 
    public LocalizedDisplayNameAttribute(string key) 
     : base(Localize(key)) 
    { 
    } 
} 
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Parameter | AttributeTargets.Delegate | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter)] 
class LocalizedCategoryAttribute : CategoryAttribute 
{ 
    public LocalizedCategoryAttribute(string key) : base(key) { } 
    protected override string GetLocalizedString(string value) 
    { 
      // TODO: lookup from resx, perhaps with cache etc 
     return "Something for " + value; 
    } 
} 
+0

मुझे कबूल करना होगा कि मैं वास्तव में समझ नहीं पाया। क्या यह है कि "desc" एक स्थानीय विशेषता के लिए एक कुंजी है? मैं निर्दिष्ट संपत्ति की विशेषता का उपयोग कैसे करूं? क्या आप कृपया अपना उदाहरण अनुकूलित कर सकते हैं? उदाहरण के लिए – 3yanlis1bos

+0

@ 3yanlis1bos मैं स्ट्रिंग का उपयोग केवल कुंजी के रूप में कर रहा हूं - आपको मैन्युअल रूप से RESX से बाहर निकलना होगा (RESX के पीछे जेनरेट की गई फ़ाइल देखें), या प्रतिबिंब –

+0

ठीक है, मुझे लगता है कि मुझे समझ में आया। आपने इनपुट की गई स्ट्रिंग को इनपुट के रूप में लेने जैसी मेरी ज़रूरतों के अनुरूप वर्णन और विस्तारित किया है। क्या वह सही है? तो केवल एक चीज जो मुझे करना है, पुराने की बजाय नई विशेषता का उपयोग करना है? – 3yanlis1bos

4
[Required(ErrorMessageResourceName = "LogOnModel_UserName_Required",  
     ErrorMessageResourceType = typeof(Resources.Global))]  
[Display(Name = "LogOnModel_UserName_Required",resourceType = typeof(Resources.Global))] 
public string UserName { get; set; } 

देखें: http://geekswithblogs.net/shaunxu/archive/2010/05/06/localization-in-asp.net-mvc-ndash-3-days-investigation-1-day.aspx

+2

चूंकि ओपी 'श्रेणी एट्रिब्यूट'/'विवरण एट्रिब्यूट' का उपयोग कर रहा है, इसलिए वे शायद * नियमित * सिस्टम से बात कर रहे हैं। कॉम्पोनेंट मॉडल ', एमवीसी नहीं - इस मामले में यह बस लागू नहीं होता है। –

+0

आह, उसे नहीं पता था। मैं ज्यादातर देव एमवीसी और सोचा था कि गुण सामान्य होंगे (यद्यपि एक महान विशेषता होगी)। – Patrick

+0

@ पैट्रिक मैंने समझ में नहीं आया :) या तो :)। सी # में थोड़े नौसिखिया। लेकिन वैसे भी कोशिश करने के लिए धन्यवाद। क्या वह "संसाधन। ग्लोबबल" था जिसे आप स्थानीयकृत संसाधन स्ट्रिंग तक पहुंचते हैं? यदि हां, तो मैं वर्णन विशेषता में ऐसा कुछ कैसे लिखूं? – 3yanlis1bos

1

ऐसा लगता है CategoryAttribute आंतरिक संसाधनों के आधार पर एक स्थानीय स्ट्रिंग देखने के लिए कोड है, लेकिन DescriptionAttribute कोई स्थानीयकरण है।

परावर्तक से:

public string Category 
{ 
    get 
    { 
     if (!this.localized) 
     { 
      this.localized = true; 
      string localizedString = this.GetLocalizedString(this.categoryValue); 
      if (localizedString != null) 
      { 
       this.categoryValue = localizedString; 
      } 
     } 
     return this.categoryValue; 
    } 
} 

मुझे लगता है कि आप विशेषताओं का विस्तार करने और ResourceType में गुजर, अपने खुद के कार्यान्वयन के लिए होगा। इस तरह कुछ, DataAnnotation तर्क पर अस्पष्ट रूप से आधारित है। स्पष्ट रूप से थोड़ा और साफ करने की जरूरत है।

public class LocaleDescriptionAttribute : DescriptionAttribute 
{ 
    ... 

    public LocaleDescriptionAttribute(string resourceKey, Type resourceType) 
     : base(resourceKey) 
    { 
     this.resourceType = resourceType; 
    } 

    public override string Description 
    { 
     get 
     { 
      var description = base.Description; 
      PropertyInfo property = resourceType.GetProperty(
         description, BindingFlags.Public | BindingFlags.Static); 
      if (property == null) 
      { 
       return description; 
      } 
      return property.GetValue(null, null) as string; 
     } 
    }  
} 
+0

दरअसल यह श्रेणी विशेषता अंतिम प्रभाव में विवरण से अलग नहीं है। मेरे पास मेरी फ़ाइल में स्थानीयकृत तार हैं, लेकिन मुझे उन्हें एक अपवाद में लागू करने जैसी विशेषता पर लागू करने की अनुमति नहीं मिल सकती है। एकमात्र चीज जिसे मैं समझने की कोशिश कर रहा हूं वह है कि कैसे एक आंतरिक स्रोत के साथ वर्णन एट्रिब्यूट भरना है जैसा आपने कहा था। – 3yanlis1bos

3

के इस नमूने वर्ग लेते हैं:

// ------------------------------------------------------------------------ 
public class Customer 
{ 
    // ---------------------------------------------------------------------- 
    [Category("Editable Values"), LocDescription("FirstName", "Sets the first name...")] 
    public string FirstName { get; set; } 

    // ---------------------------------------------------------------------- 
    [Category("Editable Values"), LocDescription( Key = "LastName", DefaultDescription = "Sets the last name...")] 
    public string LastName { get; set; } 
} // class Customer 

अब आप एक कस्टम लागू कर सकते हैं विशेषता वर्ग:

// ------------------------------------------------------------------------ 
public class LocDescriptionAttribute : DescriptionAttribute 
{ 
    // ---------------------------------------------------------------------- 
    public LocDescriptionAttribute() 
    { 
    } // LocDescriptionAttribute 

    // ---------------------------------------------------------------------- 
    public LocDescriptionAttribute(string key, string defaultDescription) : 
     base(defaultDescription) 
    { 
     Key = key; 
     DefaultDescription = defaultDescription; 
    } // LocDescriptionAttribute 

    // ---------------------------------------------------------------------- 
    public string Key { get; set; } 

    // ---------------------------------------------------------------------- 
    public string DefaultDescription { get; set; } 

    // ---------------------------------------------------------------------- 
    public override string Description 
    { 
     get 
     { 
      // load from resx 
      string description = Strings.GetString(Key); 
      if (string.IsNullOrEmpty(description)) 
      { 
       description = DefaultDescription; 
      } 
      return description; 
     } 
    } // Description 
} // class LocDescriptionAttribute 

अब आप स्थानीय वर्णन:

AttributeCollection attributes = TypeDescriptor.GetProperties(customer)[ "FirstName" ].Attributes; 
DescriptionAttribute myAttribute = (DescriptionAttribute)attributes[ typeof(DescriptionAttribute) ]; 
ConsoleWiterLine(myAttribute.Description); 
+0

मेरे पास पहले से ही एक संसाधन फ़ाइल है। मैं उन्हें अपनी चेतावनियों और संदेशों के लिए भी उपयोग करता हूं। लेकिन समस्या यह है कि, आप एक स्थानीयकरण संसाधन को विवरण विशेषता (संभव नहीं) में पास नहीं कर सकते हैं। यही मेरा मतलब है। – 3yanlis1bos

+0

मै मैक ने वही काम किया जैसा दिखता है। लेकिन मेरे लिए समझना आसान है। मुझे लगता है कि मैं इसे आजमाउंगा। – 3yanlis1bos

2

जानी के लिए थोड़ा विस्तार nswer (जो अच्छी तरह से मेरे लिए काम किया है):

string description = Strings.GetString(Key); 

अधिक स्पष्ट रूप से किया जा सकता है के रूप में

ResourceManager rm = YourResourceClassName.ResourceManager; 
string description = rm.GetString(Key); 

यह अस्पष्ट निहित था, लेकिन स्पष्ट है कि मूल कोड से लापता था नहीं था। .ResourceManager संसाधन वर्ग की संपत्ति स्वतः उत्पन्न होती है। StackOverflow बजाय hardcoding क्षेत्र/वर्ग नाम (बस DescriptionAttribute के बजाय LocDescriptionAttribute का उपयोग करें) में:

फिर, इसे उपयोग करने, विस्तार विधि Glennular यहाँ द्वारा वर्णित का उपयोग करें।

मैंने बनाया एकमात्र अन्य समायोजन इसे this IComparable enum पर स्थिर बनाने के लिए था, ताकि इसे किसी विशेष प्रकार से लॉक होने की बजाय किसी भी enum द्वारा उपयोग करने की अनुमति दी जा सके; यह सबसे अच्छा था कि मैं यह कर सकता था कि मैं इसे केवल उन enums के लिए सीमित करने के लिए एक इंटरफ़ेस लागू नहीं कर सकता, जिसमें मैंने विवरण जोड़े हैं।

2

मैं Marc Gravell संयोजित कर दी है और dsmith के जवाब:

पहले: LocalizedDescriptionAttribute के रूप में नामित एक गुण वर्ग बनाने

public class LocalizedDescriptionAttribute : DescriptionAttribute 
{ 
    static string Localize(string key) 
    { 
     return YourResourceClassName.ResourceManager.GetString(key); 
    } 

    public LocalizedDescriptionAttribute(string key) 
     : base(Localize(key)) 
    { 
    } 
} 

LocalizedDescription के रूप में यह प्रयोग करें (शब्द "गुण" आवश्यक नहीं है)

public class Foo 
{ 
    // myString is a key that exists in your Resources file 
    [LocalizedDescription("myString")] 
    public string Bar { get; set; } 
} 
संबंधित मुद्दे