+1-888-365-2779
Try Now
More in this section

Forums / Bugs & Issues / LString is a big joke

LString is a big joke

13 posts, 1 answered
  1. Nicolas
    Nicolas avatar
    156 posts
    Registered:
    19 Jan 2011
    23 Sep 2011
    Link to this post
    Hi,

    I begin to be really irritated. LString is a base type of Sitefinity API and used for translation.
    Almost 10 months since the release and a base type doesn't really work (see attachment).......

    Then 4.2 is the better version of Sitefinity but before adding tools like e-commerce. It would have been more smart to stabilize API, and to finish implementing base type.

    Regards,
    Nicolas
  2. Nicolas
    Nicolas avatar
    156 posts
    Registered:
    19 Jan 2011
    27 Sep 2011
    Link to this post
    I up my post with a complement.

    List of methods who doesn't worked :
    - Lstring.SetCurrentLanguage(CultureInfo, bool)
    - Lstring.GetString(CultureInfo, bool)
    - Lstring.GetStringNoFallback(CultureInfo)
    - Lstring.GetAllValues()
  3. Nikolay Datchev
    Nikolay Datchev avatar
    87 posts
    Registered:
    02 Jun 2016
    28 Sep 2011
    Link to this post
    Hello Nicolas,
    About your first posting and the CurrentLanguage property- i really have to agree that it brings a certain amount of misunderstanding. This property actually takes effect only when you set the Value of an Lstring object - so the setter actually sets the value of the culture that is in CurrentLanguage. By default it is set to the current thread UI culture. If you want to be sure what culture you are setting you can use the public void SetString(CultureInfo culture, string value) method.

     The Lstring.Value property getter actually returns the string value for the current thread UI  culture => System.Globalization.CultureInfo.CurrentUICulture and the getter doesn't consider the CurrentLanguage property. We will most probably hide the CurrentLanguage property in next versions since it is really confusing.

    About your second posting:
    Can you please clarify what "doesn't work" means:
    For example Lstring.GetString(CultureInfo, bool)
     => doens't return the correct value for french or
    Lstring.GetAllValues()
    doens't return any values or ?
    Lstring.GetStringNoFallback(CultureInfo) => crashes??

    Looking forward for more details
    Nikolay Datchev
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  4. Nicolas
    Nicolas avatar
    156 posts
    Registered:
    19 Jan 2011
    28 Sep 2011
    Link to this post
    Hi Nikolay,

    Quote :
    If you want to be sure what culture you are setting you can use the public void SetString(CultureInfo culture, string value) method.

    Then for obtains the Lstring example in my first post. I made it like this :
    ntArticle.Title = new Lstring();
    ntArticle.Title.SetString(new CultureInfo("en"), "Lawyer SEGL/JUR/CIB/GLF/CNR");
    ntArticle.Title.SetString(new CultureInfo("fr"), "Juriste  SEGL/JUR/CIB/GLF/CNR");

    In the end we have the visible incoherence on screen shot.


    To explains the method's list, I take in example my LString ntArticle.Title.

    Method GetString
    ntArticle.GetString(new CultureInfo("en"), true)
    Returns => "Juriste  SEGL/JUR/CIB/GLF/CNR" (French Trad).

    Method GetAllValues
    ntArticle.GetAllValues()
    Returns => null.

    Method GetStringNoFallback
    ntArticle.GetStringNoFallback(new CultureInfo("en"))
    Return => "".


    Regards,
    Nicolas
  5. Nikolay Datchev
    Nikolay Datchev avatar
    87 posts
    Registered:
    02 Jun 2016
    03 Oct 2011
    Link to this post
    Hi Nicolas,
    It looks like the problem is in the way you construct the Lstring instance. It should actually be constructed with a reference to your content item. So it should be initalized with

    ntArticle.Title = ntArticle.GetString("Title")
    GetString is an extension method in
    Telerik.Sitefinity.Model.DataExtensions
    public static Lstring GetString(this IDynamicFieldsContainer dataItem, string fieldName) 
    Even better approach is to have your Title property implemented like this:

    [DataMember] [Sortable] [CommonProperty]
    [UserFriendlyDataType(UserFriendlyDataType.ShortText)]

    public virtual Lstring Title
    {
    get {
    if (this.title == null)
    this.title = this.GetString("Title");
    return this.title; }
    set {
    this.title = value;
    this.SetString("Title", this.title);
    }
    }
    The Lstring needs to have reference to the Content item because the actual culture values are kept as separate properties inside the content item - that can be accessed only with a special TypeDescriptor - These properties are generated automatically as Open Access "artificial fields". For each such field there is a corresponding column in the database table for this content. For example for title we have title_en and title_fr columns in the db.

    So bottom-line - all Lstring methods should work just fine , if you construct the instance as suggested.

    All the best,
    Nikolay Datchev
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  6. Nicolas
    Nicolas avatar
    156 posts
    Registered:
    19 Jan 2011
    10 Oct 2011
    Link to this post
    Hi Nikolay,

    I still have a question on Lstring for NewsItem.
    I previously made a ticket, but "solution" doesn't worked now on 4.2 SP1.

    My problem is the Lstring Content field on NewsItem.

    Previously for editing it in differents languages we have to made this :
    NewsManager nMng = NewsManager.GetManager();
     
    NewsItem sfNewsMaster = nMng.CreateNewsItem();
    sfNewsMaster = nMng.Lifecycle.GetMaster(sfNewsMaster) as NewsItem;
    NewsItem sfNews = nMng.Lifecycle.CheckOut(sfNewsMaster) as NewsItem;
     
    .......
    .......
     
    Guid newsID = Guid.Empty;
     
    foreach (CultureInfo cultLang in ntArticle.Languages)
    {
           if (newsID != Guid.Empty)
           {
                   sfNewsMaster = nMng.GetNewsItem(newsID);
                   sfNewsMaster = nMng.Lifecycle.GetMaster(sfNewsMaster) as NewsItem;
                   sfNews = nMng.Lifecycle.CheckOut(sfNewsMaster) as NewsItem;
            }
     
            sfNews.Title.SetString(cultLang, ntArticle.Title.GetString(cultLang));
             
            sfNews.GetString("Content")[cultLang] =  ntArticle.RichTextContent.GetString(cultLang);
     
            sfNews.ApprovalWorkflowState.SetString(cultLang, "Published");
            sfNewsMaster = nMng.Lifecycle.CheckIn(sfNews) as NewsItem;
            nMng.RecompileItemUrls<NewsItem>(sfNewsMaster);
            nMng.Lifecycle.PublishWithSpecificDate(sfNewsMaster, ntArticle.PublishedDate, cultLang);
            try
             {
            newsID = sfNewsMaster.Id;
            nMng.SaveChanges();
             }
             catch (Exception ex)
              {
                 break;
             }
    }

    But now the only result I got with this, it's one language for "Content" NewsItem. Then I try a standard SetString as I made for "Title" field, but it doesn't worked.

    It's possible to have a solution who doesn't change at each version ?

    Regards,
    Nicolas
  7. Nikolay Datchev
    Nikolay Datchev avatar
    87 posts
    Registered:
    02 Jun 2016
    13 Oct 2011
    Link to this post
    Hello Nicolas,

    Can you elaborate on this "But now the only result I got with this, it's one language for "Content" NewsItem"
    Do you mean that you expect all language values to be copied ,since the code you pasted here is copying just one language. Also when you say the standard SetString doesn't work
    do you mean,that the following statement doesn't work:
    sfNews.SetString("Content" ntArticle.RichTextContent.GetString(cultLang), cultLang)  -> a
    and if yes - than what exactly do you mean by doesn't work.
    If you need a method to copy all languages , there is a static method CopyValues on the Lstring class.

    All the best,
    Nikolay Datchev
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  8. Nicolas
    Nicolas avatar
    156 posts
    Registered:
    19 Jan 2011
    13 Oct 2011
    Link to this post
    Hi,

    I made a foreach on CultureInfo so it's multiple languages.

    I said SetString doesn't work because if I made this :
    sfNews.Content.SetString(cultLang, ntArticle.RichTextContent.GetString(cultLang));
    The news content doesn't fill in any language.

    If I use SetString directly on NewsItem :
    sfNews.SetString("Content", ntArticle.RichTextContent.GetString(cultLang), cultLang);
    It fill only the default language.


    I also made a test of Lstring.CopyValues doesn't fill any values for this field (picture attached).


    Regards,
    Nicolas
  9. Nikolay Datchev
    Nikolay Datchev avatar
    87 posts
    Registered:
    02 Jun 2016
    19 Oct 2011
    Link to this post
    Hi Nicolas,
    You actualy hit another undocumented behaviour of the Content property. This property actually doens't return the original Lstring but a filtered Lstring which has some filters applied so any links (kept as Id's) inside the Html are resolved to real Urls. The problem is that this filter is applied only on the current culture and the lstring that you get actually has only the current culture. We are thinking to fix this inconsistent behaviour in some of the next versions.

    The proper way to inspect the real status of the Content property is by calling item.GetString("Content")  -this returns the real Lstring without those filters applied. This is something specific for the Content property, and for example for Title you don't have such problem, since we don't do resolving there.
    Also please don't look at the cultureValues[] array, to inspect what is copied and what not - test with :
    item.GetString("Content")["fr"] -> check what this returns.

    Basically a call like this copies all cutlures from one item to another
    news1.GetString("Content").CopyTo(news2.GetString("Content")) 
    in your case it can be
    ntArticle.RichTextContent.CopyTo(news2.GetString("Content"));

    and this can be done once before the for iteration.


    Also this works ok:
    news2.SetString("Content","french2","fr")
    just that in order to test if it worked you have to call:
    news2.GetString("Content")["fr"]
    not news2.Content["fr"]
    Again this is valid just for the Content proeprty - because we apply those "nasty" filters there - for title and the others it should be ok to work directly with the Property




    Best wishes,
    Nikolay Datchev
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  10. Nicolas
    Nicolas avatar
    156 posts
    Registered:
    19 Jan 2011
    20 Oct 2011
    Link to this post
    Hi,

    ok gotcha. There is a trick for made it work.

    Originally I worked on "Temp" NewsItem of "Master" like this :
    NewsManager nMng = NewsManager.GetManager();
    NewsItem sfNewsMaster = nMng.CreateNewsItem();
    sfNewsMaster = nMng.Lifecycle.GetMaster(sfNewsMaster) as NewsItem;
    NewsItem sfNews = nMng.Lifecycle.CheckOut(sfNewsMaster) as NewsItem;
    .........
    Guid newsID = Guid.Empty;
    foreach (CultureInfo cultLang in ntArticle.Languages)
     {
            if (newsID != Guid.Empty)
            {
                  sfNewsMaster = nMng.GetNewsItem(newsID);
                  sfNewsMaster = nMng.Lifecycle.GetMaster(sfNewsMaster) as NewsItem;
                  sfNews = nMng.Lifecycle.CheckOut(sfNewsMaster) as NewsItem;
            }
     
            sfNews.Title.SetString(cultLang, ntArticle.Title.GetString(cultLang));
     
            sfNews.SetString("Content", ntArticle.RichTextContent.GetString(cultLang), cultLang);
            ........................
             
            sfNews.ApprovalWorkflowState.SetString(cultLang, "Published");
            sfNewsMaster = nMng.Lifecycle.CheckIn(sfNews) as NewsItem;
            nMng.RecompileItemUrls<NewsItem>(sfNewsMaster);
            nMng.Lifecycle.PublishWithSpecificDate(sfNewsMaster, ntArticle.PublishedDate, cultLang);
     
            try
            {
                  newsID = sfNewsMaster.Id;
                  nMng.SaveChanges();
                  Telerik.Sitefinity.Abstractions.Log.Write("--- Save  --- ");
             }
            catch (Exception ex)
            {
                   Telerik.Sitefinity.Abstractions.Log.Write("--- News ECHEC --- " + ex.Message);
                    break;
            }
    }

    When I made it like this, the default language worked but second one doesn't.

    In fact the problem are the Lifecycle.CheckIn, we lost value for second language when we put it into the Master NewsItem.

    So I made it like this :
    NewsItem sfNewsMaster = nMng.CreateNewsItem();
    sfNewsMaster = nMng.Lifecycle.GetMaster(sfNewsMaster) as NewsItem;
    NewsItem sfNews = nMng.Lifecycle.CheckOut(sfNewsMaster) as NewsItem;
    .............
    Guid newsID = Guid.Empty;
     
    foreach (CultureInfo cultLang in ntArticle.Languages)
    {
          if (newsID != Guid.Empty)
          {
                 sfNews = nMng.GetNewsItem(newsID);
          }
     
          sfNews.Title.SetString(cultLang, ntArticle.Title.GetString(cultLang));
           
          sfNews.SetString("Content", ntArticle.RichTextContent.GetString(cultLang), cultLang);
     
          ...................
     
          if (newsID == Guid.Empty)
          {                           
                 sfNewsMaster = nMng.Lifecycle.CheckIn(sfNews) as NewsItem;
                 nMng.RecompileItemUrls<NewsItem>(sfNewsMaster);
                 nMng.Lifecycle.PublishWithSpecificDate(sfNewsMaster, ntArticle.PublishedDate, cultLang);
          }
          else
          {
                 nMng.RecompileItemUrls<NewsItem>(sfNews);
                 nMng.Lifecycle.PublishWithSpecificDate(sfNews, ntArticle.PublishedDate, cultLang);
          }
     
          try
          {
                 newsID = sfNewsMaster.Id;
                 nMng.SaveChanges();
                 Telerik.Sitefinity.Abstractions.Log.Write("--- Save language : --- ");
          }
          catch (Exception ex)
          {
                  Telerik.Sitefinity.Abstractions.Log.Write("--- News ECHEC --- : " + ex.Message);
                  break;
          }
    }

    I directly edit the NewsItem without use Master and Temp when I edit the second language and it works pretty well.

    It complicates code but it's effective.

    Regards,
    Nicolas
  11. Nikolay Datchev
    Nikolay Datchev avatar
    87 posts
    Registered:
    02 Jun 2016
    27 Oct 2011
    Link to this post
    Hello Nicolas,
    I am glad you manage to make it work, i guess we can close this thread for now.

    Kind regards,
    Nikolay Datchev
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
    Answered
  12. Pete
    Pete avatar
    3 posts
    Registered:
    01 Dec 2014
    23 Sep 2015
    Link to this post

    I know this is an old thread, but the topic still holds weight. Over the last year of developing with Sitefinity I've battled Lstring again and again. Just ran into another issue today where some reflection code was not mapping values, because a type check was in place and typeof(String) != typeof(Lstring). Excellent, so we have to put in a specific check just for Lstring to allow the mapping!

    Why oh why did you have to expose your own custom String object Telerik? It causes far more frustration than any help it provides.

  13. Shriyal
    Shriyal avatar
    2 posts
    Registered:
    25 May 2016
    01 Sep
    Link to this post

    I totally agree with how tiring this is

    See code

                var folderList = dynamicModuleManager.GetDataItems(videoFolderType).Where(i => i.Status == ContentLifecycleStatus.Master);
                if (folderList == null)
                {
                    throw new NotFoundException("Embed Video Module");
                }

                var xList = folderList.Select(f => f.UrlName).ToList();

    this var xList fails. And I tried f.UrlName.value, f.UrlName.ToString(). 

    That ToString() fails with : Method 'ToString' is not supported on the 'System.Object' type. I am totally out of ideas. And this is the first hit in Google.

    Good job LString.

    Edit: This is what worked (see below)

    List<string> retList = new List<string>();
                foreach (var item in folderList)
                {
                    string sad;
                    bool xFound = item.UrlName.TryGetValue(out sad);
                    if (xFound)
                        retList.Add(sad);
                    else
                        retList.Add("not found folder Name");
                }

    -- but .value fails with : Property 'System.String Value' is not defined for type 'System.String'.

     

13 posts, 1 answered