LString is a big joke

Posted by Community Admin on 04-Aug-2018 15:03

LString is a big joke

All Replies

Posted by Community Admin on 23-Sep-2011 00:00

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

Posted by Community Admin on 27-Sep-2011 00:00

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()

Posted by Community Admin on 28-Sep-2011 00:00

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

Posted by Community Admin on 28-Sep-2011 00:00

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

Posted by Community Admin on 03-Oct-2011 00:00

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

Posted by Community Admin on 10-Oct-2011 00:00

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

Posted by Community Admin on 13-Oct-2011 00:00

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

Posted by Community Admin on 13-Oct-2011 00:00

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

Posted by Community Admin on 19-Oct-2011 00:00

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

Posted by Community Admin on 20-Oct-2011 00:00

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

Posted by Community Admin on 27-Oct-2011 00:00

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

Posted by Community Admin on 23-Sep-2015 00:00

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.

Posted by Community Admin on 01-Sep-2016 00:00

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'.

 

Posted by Community Admin on 20-Dec-2016 00:00

Another one...

libraryManager.GetChildFolders( currentFolder ).FirstOrDefault( x => x.Title.TrimEnd( '-' ) == subFolderName )

is shown in intellisense, but errs out with:

Method 'TrimEnd' is not supported on the 'Telerik.Sitefinity.Model.Lstring' type.

Things like this end up costing hours of work.  When I replace a common and expected type with my own, I usually inherit the base type.  If this is not possible or practical, I replicate every call unless there is a compelling reason not to (in which case I document it).  It is a lot of work sometimes, but makes maintenance much easier.  As Lstring is replacing string, it would be nice if it included all of the normal things you can do with a string.

This thread is closed