Project Description
jstring is a small c# library that provides multilingual string support. The jstring class provides programmatic support for projects that require the ability to change languages on-the-fly.

jString is designed to be a logical extension of the string class. It is a wrapper class for a sparse collection (array) of jlets (j-string-let), where a jlet is a structure containing a string and language identifier.

jString owes it name the Jetfire project, where jString provides multilingual support for the Jetfire language which makes it very easy to develop business rules (Business Rule Engine), persistent programs and workflows.

It supports:
  • + or concatenate operator
  • | or merge operator
  • * or addall/prepend operator
  • indexing by language with fallback
  • ToXml and TryParse providing conversion to, and from, XElements

jString has a few support classes
  • jlet (jStringlet)- A simple structure that wraps a single .net 'string' object with a language id and string type.
  • Lang - an enumeration class that describes languages.
  • CLR Extensions - provides extension methods for CLR classes such as XElement to easily work with jString.
  • jStringlet Extensions - provides extension methods to support collections of jlet (IEnumerable<jlet>)

jString Assignment
       jstring j = "my string";        // create a jstring
       string s2 = (string)j["en"];
       string s3 = (string)j;          // convert a 'jstring' to a .net string 
       Assert.AreEqual("my string", s2);
       Assert.AreEqual("my string", s3);
       Assert.AreEqual("my string", (string)j["en"]);

Multilingual Add or Concatenate
       jstring s1 = jstring.Create(
       jstring s2 = " David".fr() | " David".en();
       jstring s3 = s1 + s2;            // add english stringlets and french stringlets
       Assert.AreEqual("hello David", (string)s3["en"]);
       Assert.AreEqual("bonjour David", (string)s3["fr"]);

       jstring j ="bonjour") | jlet.en("hello") |"guten tag");
       string sum = "";
       int i = 0;
       foreach (string s in j)
            sum += s;
       Assert.AreEqual(3, i);
       Assert.AreEqual("bonjourhelloguten tag", sum);

       jstring j1 = jlet.fr_CA("breuvage") |"boisson") | jlet.en("beverage");
       jstring j2 ="boisson") | jlet.en("beverage");
       jstring j3 = jlet.en("beverage");
       Lang[] frCA_withfallback = new Lang[]{

       Assert.AreEqual("breuvage", (string)j1[ frCA_withfallback]);
       Assert.AreEqual("boisson", (string)j2[ frCA_withfallback]);
       Assert.AreEqual("beverage", (string)j3[ frCA_withfallback]);

    jstring j1 = "breuvage".fr_CA() | "boisson".fr() | "beverage".en();
          jstring j2 = j1.AddAll(":");
          Assert.AreEqual("breuvage:", (string)j2[Lang.fr_CA]);
          Assert.AreEqual("boisson:", (string)j2[]);
          Assert.AreEqual("beverage:", (string)j2[Lang.en]);
          jstring j2 = j1 * ":";
          Assert.AreEqual("breuvage:", (string)j2[Lang.fr_CA]);
          Assert.AreEqual("boisson:", (string)j2[]);
          Assert.AreEqual("beverage:", (string)j2[Lang.en]);
      // add at the beginning of j1 (prepend)
           jstring j2 = "->".AddAll(j1);
           Assert.AreEqual("->breuvage", (string)j2[Lang.fr_CA]);
           Assert.AreEqual("->boisson", (string)j2[]);
           Assert.AreEqual("->beverage", (string)j2[Lang.en]);
           jstring j2 = "->" * j1;
           Assert.AreEqual("->breuvage", (string)j2[Lang.fr_CA]);
           Assert.AreEqual("->boisson", (string)j2[]);
           Assert.AreEqual("->beverage", (string)j2[Lang.en]);

Custom Operations
  • This demonstrates using Linq to develop custom operations.
    jstring j1 = "breuvage".fr_CA() | "boisson".fr() | "beverage".en() | "getränk".de();
    Assert.AreEqual(4, j1.Count);

    // remove 'english' and 'french' from 'j1'
    jstring j2 = j1.Where(j => !(j.LanguageID == (ushort)Lang.en || j.LanguageID == (ushort);
    Assert.AreEqual(2, j2.Count);

Last edited Mar 28, 2012 at 12:15 PM by JohnHansen, version 29