.NET

6

में चरम ब्रांडिंग/अंतर्राष्ट्रीयकरण कैसे करें हम एक बहुत बड़े आवेदन की योजना बना रहे हैं।.NET

-हम 30 देशों के लिए हमारे आवेदन को अंतर्राष्ट्रीय बनाना चाहते हैं।

- अधिकांश देशों में 1 से 6 विभिन्न ब्रांड उपलब्ध हैं।

-Each एक निश्चित और 'XXX' की तरह 'डी' की तरह वातावरण ब्रांड के संयोजन कई बार हो सकता है इसलिए हम एक और पहचानकर्ता की जरूरत है कुछ अद्वितीय पाने के लिए:

"locale_brand_siteorigin" 

इसलिए हम जैसे .resx फ़ाइल है:

कॉन्फ़िगरेशन। de.burgerking.px10 .resx

बोल्ड मुद्रित अद्वितीय पहचानकर्ता है।

var rm = new ResourceManager("MyNamespace.Configurations.UniqueIdentifier",Assembly.GetExecuting()); 

हमारे व्यापार तर्क के आधार पर हम ऊपर संसाधनप्रबंधक बना सकते हैं:

रनटाइम के दौरान हम एक बना सकते हैं।

अंत में हम अद्वितीय पहचानकर्ता के सभी संयोजनों के साथ 180+ resx फ़ाइलों को समाप्त कर देंगे।

क्या आप इस तरह के ब्रांडिंग करने के बेहतर तरीके से जानते हैं?

4 साल पहले किसी को इस प्रश्न पूछा, लेकिन कोई भी उत्तर दिया:

Industry standard for implementing application branding?

अद्यतन

मैं भी मेरे सवाल उपयोग कर के लाभ दिखा एक समाधान के लिए पूछ का विस्तार करना चाहते cultureandregioninfobuilder कक्षा उन कई कस्टम संस्कृतियों को बनाने के लिए।

https://msdn.microsoft.com/en-us/library/system.globalization.cultureandregioninfobuilder(v=vs.110).aspx

+0

आपको इसके लिए अपने स्वयं के समाधान को लागू करने की अधिक संभावना होगी, लेकिन यह आसान है। संसाधन आईडी, संस्कृति, ब्रांड (शून्य), मान, डिफ़ॉल्ट मानों पर फ़ॉलबैक के साथ डेटाबेस में बस कुछ तालिका (प्रत्येक संसाधन प्रति ब्रांड को स्थानीयकृत नहीं किया जाना चाहिए)। और निश्चित रूप से स्मृति में अनुप्रयोग स्टार्टअप पर कैश। अपने कोडबेस के साथ ऐसी चीजों को एक साथ रखना एक अच्छा विचार नहीं है - उन्हें कोड की तुलना में अधिक बार कम अपडेट की आवश्यकता हो सकती है। – Evk

उत्तर

2

मैं इतनी बड़ी परियोजना के लिए फ़ाइलों .resx उपयोग करने की अनुशंसा नहीं होता। जब कई वेबसाइटों में एक वेबसाइट का अनुवाद किया जाता है, आमतौर पर बहुत से लोग कॉपी प्रबंधन, अनुवाद इत्यादि में शामिल होते हैं। ये लोग .resx फ़ाइलों को संपादित करने में सक्षम नहीं होंगे क्योंकि वे तकनीकी कोड में तकनीकी रूप से एम्बेडेड हैं। इसका मतलब यह है कि आपके डेवलपर्स को हर बार परिवर्तनों को अद्यतन करना होगा ... हर किसी के लिए असली दुःस्वप्न।

मैंने हाल ही में SumoSoft.Cms के लिए डेटाबेस संचालित प्रणाली का निर्माण किया है। सभी श्रृंखलाएं, व्यवस्थापक पैनल के माध्यम से नियंत्रित किया जा सकता है, जबकि कोड में आप सिर्फ का उपयोग करें:

@CmsMethods.StringContent("ContentSection_Name", "Fallback_Value") 

यह हेल्पर डाटाबेस क्वेरी लिखते "ContentSection" की एक इकाई को कमोबेश इस तरह संरचित है की तलाश में:

public class ContentSection 
{ 
    public string Name { get; set; } 

    public ICollection<ContentSectionLocalizedString> LocalizedStrings { get; set; } 
} 

प्रत्येक लोकलाइज्डस्टिंग में एक विशिष्ट देश और संपत्ति "सामग्री" का संदर्भ होता है, इसलिए सभी हेल्पर थ्रेड की वर्तमान संस्कृति से मेल खाने वाले व्यक्ति को चुनना है।

1

@ FrancescoLorenzetti84 जवाब विस्तार करते हुए, एक तरह से मैंने पहले भी यह किया है यह आसान बनाए रखने के लिए बनाने के लिए एक ResourceString कक्षा में डेटाबेस पुनर्प्राप्ति रैप करने के लिए है, ताकि आप की तरह कुछ कर सकते हैं:

private static readonly ResourceString res = "The value"; 

और उसके बाद कोड में देखें। दृश्य के पीछे, संसाधन स्ट्रिंग क्लास काम करता है।

namespace ResString 
{ 

    public interface IResourceResolver 
    { 
     string Resolve(string key, string defaultValue); 
    } 

    public class ResourceString 
    { 
     public ResourceString(string value) 
     { 
      this.defaultValue = value; 
      GetOwner(); 
     } 

     public string Value 
     { 
      get 
      { 
       if (!resolved) 
        Resolve(); 
       return value; 
      } 
     } 

     public override string ToString() 
     { 
      return Value; 
     } 

     public static implicit operator string(ResourceString rhs) 
     { 
      return rhs.Value; 
     } 

     public static implicit operator ResourceString(string rhs) 
     { 
      return new ResourceString(rhs); 
     } 

     protected virtual void Resolve() 
     { 
      if (Resolver != null) 
      { 
       if (key == null) 
        key = GetKey(); 
       value = Resolver.Resolve(key, defaultValue); 
      } 
      else 
      { 
       value = defaultValue; 
      } 
      resolved = true; 
     } 

     [MethodImpl(MethodImplOptions.NoInlining)] 
     protected virtual void GetOwner() 
     { 
      StackTrace trace = new StackTrace(); 
      StackFrame frame = null; 
      int i = 1; 
      while (i < trace.FrameCount && (owner == null || typeof(ResourceString).IsAssignableFrom(owner))) 
      { 
       frame = trace.GetFrame(i); 
       MethodBase meth = frame.GetMethod(); 
       owner = meth.DeclaringType; 
       i++; 
      } 
     } 

     protected virtual string GetKey() 
     { 
      string result = owner.FullName; 
      FieldInfo field = owner.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static).Where(f => 
       typeof(ResourceString).IsAssignableFrom(f.FieldType) && f.GetValue(null) == this 
      ).FirstOrDefault(); 
      if (field != null) 
       result += "." + field.Name; 
      return result; 
     } 


     public static IResourceResolver Resolver { get; set; } 

     private string defaultValue; 
     private string value; 

     private bool resolved; 
     private string key; 
     private Type owner; 


    } 
} 

और एक उदाहरण कार्यक्रम:: यहाँ कि का एक उदाहरण है

namespace ResString 
{ 
    class Program 
    { 
     /// <summary> 
     /// Description for the first resource. 
     /// </summary> 
     private static readonly ResourceString firstRes = "First"; 
     /// <summary> 
     /// Description for the second resource. 
     /// </summary> 
     private static readonly ResourceString secondRes = "Second"; 
     /// <summary> 
     /// Description for the format string. 
     /// </summary> 
     private static readonly ResourceString format = "{0} {1}"; 

     static void Main(string[] args) 
     { 
      ResourceString.Resolver = new French(); 
      Console.WriteLine(String.Format(format, firstRes, secondRes)); 
     } 

     private class French : IResourceResolver 
     { 
      public string Resolve(string key, string defaultValue) 
      { 
       switch (key) 
       { 
        case "ResString.Program.firstRes": 
         return "Premier"; 
        case "ResString.Program.secondRes": 
         return "Deuxième"; 
        case "ResString.Program.format": 
         return "{1} {0}"; 
       } 

       return defaultValue; 
      } 
     } 

    } 
} 

आपको लगता है कि चलाते हैं, तो यह होगा उत्पादन: Deuxième प्रीमियर

टिप्पणी बाहर रिज़ॉल्वर असाइनमेंट और आप करेंगे प्राप्त करें: पहला दूसरा

कोई भी जहां आप UI में स्ट्रिंग का उपयोग करेंगे, इसके बजाए घोषित संसाधन संसाधन का उपयोग करें।

स्ट्रिंग मानों को हल करने के बाद रिज़ॉल्वर को बदलना उनके मान को परिवर्तित नहीं करेगा क्योंकि मान केवल एक बार पुनर्प्राप्त किए जाते हैं। आपको निश्चित रूप से एक वास्तविक रिज़ॉल्यूवर लिखना होगा जो डेटाबेस से खींचता है।

आपको फिर से कंप्यूटरीकृत कक्षाओं के माध्यम से चलाने के लिए उपयोगिता कार्यक्रम की आवश्यकता होगी और संसाधनस्ट्रिंग घोषणाओं को खींचें और कुंजी और डिफ़ॉल्ट मान डेटाबेस या टेक्स्ट फ़ाइल में डाल दें ताकि उनका अनुवाद किया जा सके। यह प्रत्येक असेंबली के लिए जेनरेट की गई सहायता एक्सएमएल फाइलों के माध्यम से भी जाना चाहिए और संसाधनस्ट्रिंग घोषणाओं के लिए टिप्पणी खींचना चाहिए ताकि अनुवादक के पास काम करने के लिए कुछ संदर्भ हो। मुख्य घोषणाएं संदर्भ भी प्रदान करेंगी क्योंकि आप आसानी से यूआई कक्षा द्वारा संसाधनों को समूहबद्ध कर सकते हैं।

इसे एक बिल्ड स्क्रिप्ट में जोड़ें, सुनिश्चित करें कि यह नियमित रूप से अपडेट हो।

आप छवियों और इसी तरह के साथ एक ही दृष्टिकोण का उपयोग कर सकते हैं।