Resource and Culture and UICulture (והשמה אוטומטית של מידע)

9 במאי 2009

 


קבצי resource הם דרך נהדרת לשמור את ההודעות והטקסט של האפליקצייה לפי ה culture,

 

הדבר שמעצבן אותי כמפתח, שאני צריך בכל פעם לכתוב את הקוד של ההשמה מתוך קובץ ה resource על ה label המתאים.

 

אז לפני שאני אראה את הפיתרון שאני משתמש, נעשה מעבר מהיר על הנושא. לטובת אלו שלא יודעים מה זה resource ומה זה culture.

 

 

נניח שיש לי אפליקצייה שאני רוצה שתהיה גם באנגלית וגם בעברית, נתעלם לרגע מהעובדה שכיון הכתיבה הוא הפוך, ונתמקד בזה שהטקסט צריך להיות בשתי השפות.

 

איך נעשה את זה ?

 

קליק ימין עם העכבר על הפרויקט שלנו, נבחר ב add new item, ונבחר ב  Resource

 

 

Resource 1

 

 

אני נוהג לייצר קובץ עבור כל דף, והשם של ה resource הוא בדרך כלל השם של הדף.

 

כעת נוסיף עוד קובץ resource שהשם שלו יהיה זהה לשם של הקובץ הקודם, אבל עם סיומת של ה culture, לדוגמא: Default.he-IL.resx,

 

אחרי שנוסיף את הקבצים, ונתחיל לערוך אותם, נוכל להוסיף ערכים, שהם למעשה key-value, כשה key, יהיה זהה בשני הקבצים, אבל ה value, יהיה שונה, לדוגמא:

 

(העליון הוא הקובץ עם הסיומת של he-IL)

 

Resource2

 

 

וכעת בקוד מה שאנחנו צריכים לעשות, זה לתת לכל label, את הkey המתאים,

 

לדוגמא:

 



    protected void Page_Load(object sender, EventArgs e)


    {


        lblHello.Text = Default.lblHello;


        lblWelcome.Text = Default.lblWelcome;


    }


 

כעת נשאר לנו רק לקבוע, מאיזה קובץ לקחת את הערכים,

 

אז למעשה יש כמה דרכים, אפשר מקונפיג, אפשר על ידי הגדרות הדף, כאן אפשר לקרוא מאמר שמסביר את הנושא.

 

אני בדרך כלל עושה את זה מקוד, צריך לעשות override ל InitializeCulture, ושם להחליט מה ה resource המתאים,

 

יש לדף שני properties שמחליטים על הסביבה, הראשון, הוא ה Culture, זה אינו קשור אלינו, הוא מחליט באיזה פורמט יוצגו המספרים ותאריכים,

 

לדוגמא הקוד הבא,

 



    protected void Page_Load(object sender, EventArgs e)


    {


        lblTime.Text = DateTime.Now.ToLongDateString();


    }


 


    protected override void InitializeCulture()


    {


        Culture = "he-IL";


    }


 

יחזיר את התוצאה: שבת 09 מאי 2009

 

לעומת זאת הקוד הבא:

 



    protected void Page_Load(object sender, EventArgs e)


    {


        lblTime.Text = DateTime.Now.ToLongDateString();


    }


 


    protected override void InitializeCulture()


    {


        Culture = "en-US";


    }


 

יחזיר את התוצאה: Saturday, May 09, 2009

 

אבל כמו שאמרתי, זה לא המאפיין שכרגע אנחנו מדברים עליו, אנחנו מדברים על המאפיין UICulture,

הוא מחליט מאיזה קובץ resource לקחת את הערכים, ולכן הקוד הבא:

 



    protected void Page_Load(object sender, EventArgs e)


    {


        lblHello.Text = Default.lblHello;


        lblWelcome.Text = Default.lblWelcome;


    }


 


    protected override void InitializeCulture()


    {


        UICulture = "he-IL";


    }


 

יחזיר את הערכים מתוך קובץ ה resource עם סיומת ה he-IL,

 

לעומת זאת הקוד הבא:

 



    protected void Page_Load(object sender, EventArgs e)


    {


        lblHello.Text = Default.lblHello;


        lblWelcome.Text = Default.lblWelcome;


    }


 


    protected override void InitializeCulture()


    {


        UICulture = "en-US";


    }


 

יחזיר את הערכים, מתוך הקובץ הרגיל (ללא סיומת של תרבות כלשהו).

 

בעייה אחת, יש לזה, שבמידה ואנחנו צריכים גישה לערכים מתוך ה javascript, אין לנו, הפיתרון לזה, נמצא כאן.

 

והבעייה האחרונה (שלכבודה נכתב כל הפוסט הזה),

 

אני לא רוצה כמפתח לדאוג להשמה של כל הערכים על ה labels השונים, אז כדי לפתור את זה כתבתי את הפיתרון הבא:

 

בקבצי ה resource, השמות שאני נותן ל keys הם שם האובייקט_שם המאפיין לדוגמא:

 

resource3

 

 

שני הראשונים, הם שמות של label ומאפיין הטקסט שלהם, האחרון הינו RequiredFieldValidator ומאפיין ErrorMessage.

 

כעת בקוד אני מפעיל את המתודה הבאה:

 



private void SetDataFromResource()


{


    Type type = typeof(Default);


    PropertyInfo[] properties = type.GetProperties(BindingFlags.NonPublic | BindingFlags.Static);


 


    var stringProperties = from property in properties


                           where property.PropertyType == typeof(string)


                           select new Pair(property.Name, property.GetValue(null, null));


 


    foreach (var item in stringProperties)


    {


        string[] arr = item.First.ToString().Split('_');


        if (arr.Length == 2)


        {


            Control ctr = FindControl(arr[0]);


            if (ctr != null)


            {


                PropertyInfo pi = ctr.GetType().GetProperty(arr[1]);


                if (pi != null)


                {


                    pi.SetValue(ctr, item.Second.ToString(), null);


                }


            }


        }


    }


}


 

אני מוציא את כל הערכים מתוך קובץ ה resource.

 

מחפש control עם השם של האובייקט, במידה ואני מוצא, אני משים את הערך למאפיין.

 

 

הפיתרון הזה הוא לא כל כך טוב מבחינת ביצועים, אבל במידה והנקודה הזאת לא מפריעה, אז זה פותר לי את הבעייה שאני צריך לדאוג להשים את הערכים למקומות המתאימים

הוסף תגובה
facebook linkedin twitter email

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *

5 תגובות

  1. Rotem Bloom10 במאי 2009 ב 9:13

    תראה שלמה בגדול אתה צודק זה לא ממש נוח לנהל את כל קיבצי ה-RESOURCES אבל אם יש לך אפליקציה פשוטה יחסית ולא מעניין אותך ביצועים .NET יכול לאפשר לך לעשות את הכל בצורה אוטומטית.
    אז אתה רוצה לדעת איך עושים את זה עם VS 2008 בבקשה:
    1) תפתח את קובץ ה-ASPX שלך במצב של DESIGN
    2) ב-VS תלחץ כל TOOLS ואז תבחר GENERATE LOCAL RESOURCE

    מה שזה בעצם יעשה לך זה יצור לך קובץ RESOURCE שיכיל לך כבר את כל המפתחות כולל טקסט לכל ה-CONTROLS שלך. מה שישאר לך זה רק להעתיק את הקובץ לפי שפה ולתרגם את הטקסט בהתאם.
    כמובן שעדיף לעשות את זה ממש בסוף שכל הדף שלך כבר מוכן אחרת בכל עידכון תצטרך לייצר את הקובץ מחדש.

    מקווה שזה יעזור לך לדעתי זה קצת מקל על העבודה ועל ההתעסקות בכל נושא ה-RESOURCES.

    שוב הפיתרון הזה הוא לא הכי מושלם בעיקר כי הוא משכפל לך ערכי תירגום ולא עובד עם GLOBAL RESORCES אבל בהחלט מקל על יצירת ה- LOCAL RESOURCE.

    ביי רתם

    הגב
  2. Shlomo10 במאי 2009 ב 9:25

    לא הכרתי, תודה

    הגב
  3. עמירם16 ביולי 2009 ב 13:52

    תודה רבה , הפוסט הזה עזר לי המון , שברתי את הראש ימים עד שראיתי את השורות האלו
    protected override void InitializeCulture()

    {

    Culture = "he-IL";

    }
    משום מה כשאני נמצא בסביבת הפיתוח , התאריך מוצג לי בפורמט המתאים dd/MM/yyyy
    אבל בסביבת הפרוד , משום מה התאריך מוצג כUS , בפורמט MM/dd/yyyy

    אני מקווה שזה יפתור לי את הבעיה ,
    אתה ממליץ לשים את הקוד הזה ב Master Page ? או בכל דף בנפרד ?

    שוב,
    תודה

    הגב
  4. Shlomo16 ביולי 2009 ב 14:16

    ה – MasterPage יכול להיות אפשרות.
    אני הייתי ממליץ לך לעשות class בשם PgaeBase שיורש מ – Page וכל הדפים יורשים ממנו ושם לעשות את זה (וכן את כל הקוד המשותף) כי Page לר יורש מ – masterPage אלא מכיל אותו (כי הוא UserControl).

    אופצייה נוספת היא: ב – Config
    אתה יכול להוסיף כניסה בשם globalization שבו אתה יכול לקנפג את ה – uiCulture ואת ה – culture

    הגב
  5. עמירם17 ביולי 2009 ב 11:14

    היי,
    תודה רבה , זה באמת עזר!
    הוספתיבWEBCONFIOG , הגדרה של globaliztaion , וזה תר לי את הבעיה.

    תודה רבה !

    הגב