GUIDE: Right to Left Languages Support for jQuery Mobile


I am developing a mobile application using jQuery and was looking for a solution for RTL languages support for jQuery Mobile. Unfortunately I found none. I had to do it my self.  Please keep in mind that the file might not be complete, I have gradually updated it so that my application works. You might be using more components that needs further changes.

You can download the file from here

In case you still had any issues, the tips below helps you to fix the situation, I hope J.

  1. Add a direction attribute with “rtl” value to the body CSS
  2. Overwrite all css classes that has “float:right” with “float:left” and vise versa
  3. Overwrite all css classes that has “left:” with “right:” and vise versa. It is worth mentioning her that you keep the previous attribute and make it auto. Else it won’t work.
    i.e. left:15px   should be overwrite with left:auto;right:15px.
  4. Do the same as point 3 for all classes that has margin-left, margin-right, padding-left and padding-right

That’s it, please enjoy it and let me know if you’ve any comments or questions

UPDATE: I stumbled upon another version for achieving this. I believe it’s more comprehensive than mine J. Please check http://stackoverflow.com/questions/6321271/jquery-mobile-right-to-left-css

Advertisements

16 thoughts on “GUIDE: Right to Left Languages Support for jQuery Mobile

  1. Thanks, this seems to get work nicely.
    I think you should also change text-align:left / text-align:right.
    Also there is also short format of margin/padding.

    Now I’m trying to write a tool to do this automatically…

      • Try this code:

        You pass is the css filename on the command line (i.e. test.css) and it created a file for RTL (test.RTL.css)

        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Text;
        using System.IO;
        using System.Text.RegularExpressions;

        namespace RTL_CSS
        {
        // todo: check to see if works on minified CSS.
        class Program
        {
        static void Main( string[] args )
        {
        foreach (var f in args)
        {
        var d=Path.ChangeExtension(Path.GetFileNameWithoutExtension(f)+”.RTL.”, Path.GetExtension(f));
        d=Path.Combine(Path.GetDirectoryName(f), d);
        RTL(f, d);
        }
        }

        private const char MarkerChar=(char)0;

        static private Regex ws=new Regex(@”\s*”);

        private static void RTL( string s, string d )
        {
        var text=File.ReadAllText(s);

        var transforms=GetTransforms();
        var regex=CreateRegex(transforms);

        var replaced=regex.Replace(text, ( m ) =>
        {
        string k = Normalize(m.Value);
        string value;
        if (transforms.TryGetValue(k, out value))
        {
        Console.WriteLine(m.Value+”=>”+value);
        return value;
        }
        else
        {
        return m.Value;
        }
        });
        File.WriteAllText(d, replaced);
        }

        private static string Normalize( string str )
        {
        return ws.Replace(str, “”).ToLower();
        }

        private static Regex CreateRegex( Dictionary transforms )
        {
        string regex=string.Join(“|”, transforms.Keys.Select(t => string.Format(“(?:{0})”, t.Replace(“:”, @”\s*:\s*”))));
        regex=string.Format(“(?<![-a-zA-Z])({0})", regex);
        return new Regex(regex);
        }

        private static Dictionary GetTransforms()
        {
        var n=new Dictionary{
        {“float:right”,”float: left”},
        {“float:left”,”float: right”},
        {“left:”,”left:auto; right:”},
        {“right:”,”right:auto; left:”},
        {“text-align:left”,”text-align: right”},
        {“text-align:right”,”text-align: left”},
        {“margin-left:”,”margin-left:auto; margin-right:”},
        {“margin-right:”,”margin-right:auto; margin-left:”},
        {“padding-left:”,”padding-left:auto; padding-right:”},
        {“padding-right:”,”padding-right:auto; padding-left:”},
        };
        // normalize keys.
        return n.ToDictionary(v => Normalize(v.Key), v => v.Value);
        }
        }
        }

  2. There is my case I found that my code does not handle properly and that is the ui-header-fixed/ui-footer-fixed classes that specify both left & right attributes.

    • I use the following c# code to modify the css:

      using System;
      using System.Collections.Generic;
      using System.ComponentModel;
      using System.Data;
      using System.Drawing;
      using System.Linq;
      using System.Text;
      using System.Windows.Forms;
      using System.IO;
      using System.Text.RegularExpressions;

      namespace ConvertJqueryMobileToRtl
      {
      public partial class Form1 : Form
      {
      public Form1()
      {
      InitializeComponent();
      }

      private void button1_Click(object sender, EventArgs e)
      {
      string cssContent = “”;

      StreamReader rd = new StreamReader(“jquery.mobile-1.1.1.min.css”, Encoding.GetEncoding(1255));
      cssContent = rd.ReadToEnd();
      rd.Close();
      cssContent = cssContent.Replace(“{“, “{\n”);
      cssContent = cssContent.Replace(“;”, “;\n”);
      cssContent = cssContent.Replace(“}”, “\n}\n\n”);

      string[] lines = cssContent.Split(‘\n’);
      StringBuilder sb = new StringBuilder();
      foreach (string line in lines)
      {
      string line1 = line.Replace(“right:”, “temp:”);
      line1 = line1.Replace(“right;”, “temp;”);
      line1 = line1.Replace(“left:”, “right:”);
      line1 = line1.Replace(“left;”, “right;”);
      line1 = line1.Replace(“temp:”, “left:”);
      line1 = line1.Replace(“temp;”, “left;”);
      line1 = Regex.Replace(line1, @”padding:(\d+)px (\d+)px (\d+)px (\d+)px”, “padding:$1px $4px $3px $2px”);
      sb.Append(line1);
      }

      cssContent = @”body{direction:rtl}
      .ui-icon-arrow-r{background-position: -144px 50%;}
      ” + sb.ToString().Replace(“\n”, “”);
      StreamWriter wr = new StreamWriter(“jquery.mobile-1.1.1.min.rtl.css”, false, Encoding.GetEncoding(1255));
      wr.Write(cssContent);
      wr.Close();
      }
      }
      }

  3. Tomer,

    I don’t think your code handles the float:and text-align attributes.
    Also I does not handle margin.

    Nadav

  4. I changed the code to:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    using System.Text.RegularExpressions;

    namespace ConvertJqueryMobileToRtl
    {
    public partial class Form1 : Form
    {
    public Form1()
    {
    InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
    string cssContent = “”;

    StreamReader rd = new StreamReader(“jquery.mobile-1.1.1.min.css”, Encoding.GetEncoding(1255));
    cssContent = rd.ReadToEnd();
    rd.Close();
    cssContent = cssContent.Replace(“{“, “{\n”);
    cssContent = cssContent.Replace(“;”, “;\n”);
    cssContent = cssContent.Replace(“}”, “\n}\n\n”);

    string[] lines = cssContent.Split(‘\n’);
    StringBuilder sb = new StringBuilder();
    foreach (string line in lines)
    {
    string line1 = line.Replace(“right:”, “temp:”);
    line1 = line1.Replace(“right;”, “temp;”);
    line1 = line1.Replace(“left:”, “right:”);
    line1 = line1.Replace(“left;”, “right;”);
    line1 = line1.Replace(“temp:”, “left:”);
    line1 = line1.Replace(“temp;”, “left;”);

    line1 = line1.Replace(“margin-right:”, “margin-temp:”);
    line1 = line1.Replace(“margin-left:”, “margin-right:auto;margin-left:”);
    line1 = line1.Replace(“margin-temp:”, “margin-left:auto;margin-right:”);

    line1 = line1.Replace(“padding-right:”, “padding-temp:”);
    line1 = line1.Replace(“padding-left:”, “padding-right:auto;padding-left:”);
    line1 = line1.Replace(“padding-temp:”, “padding-left:auto;padding-right:”);

    line1 = Regex.Replace(line1, @”padding:(\d+)px (\d+)px (\d+)px (\d+)px”, “padding:$1px $4px $3px $2px”);
    sb.Append(line1);
    }

    cssContent = @”body{direction:rtl}
    .ui-icon-arrow-r{background-position: -144px 50%;}
    ” + sb.ToString().Replace(“\n”, “”);
    StreamWriter wr = new StreamWriter(“jquery.mobile-1.1.1.min.rtl.css”, false, Encoding.GetEncoding(1255));
    wr.Write(cssContent);
    wr.Close();
    }
    }
    }

    Now, to me, it works just fine…

  5. I changed the code. It is not “nice”, but now panel transitions works well. Try it…

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    using System.Text.RegularExpressions;

    namespace ConvertJqueryMobileToRtl
    {
    public partial class Form1 : Form
    {
    public Form1()
    {
    InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
    string cssContent = “”;

    StreamReader rd = new StreamReader(“jquery.mobile-1.3.0.min.css”, Encoding.GetEncoding(1255));
    cssContent = rd.ReadToEnd();
    rd.Close();
    cssContent = cssContent.Replace(“{“, “{\n”);
    cssContent = cssContent.Replace(“;”, “;\n”);
    cssContent = cssContent.Replace(“}”, “\n}\n\n”);

    string[] lines = cssContent.Split(‘\n’);
    StringBuilder sb = new StringBuilder();
    bool wastranslate3d = false;
    bool stopRTL = false;
    foreach (string line in lines)
    {
    if (line.Contains(“-webkit-transform:translate3d(0,0,0)”))
    wastranslate3d = true;
    if (line.Contains(“.ui-panel-position-left”) && wastranslate3d)
    {
    stopRTL = true;
    }
    if (stopRTL)
    {
    sb.Append(line);
    }
    else
    {
    string line1 = line.Replace(“right:”, “temp:”);
    line1 = line1.Replace(“right;”, “temp;”);
    line1 = line1.Replace(“left:”, “right:”);
    line1 = line1.Replace(“left;”, “right;”);
    line1 = line1.Replace(“temp:”, “left:”);
    line1 = line1.Replace(“temp;”, “left;”);

    line1 = line1.Replace(“margin-right:”, “margin-temp:”);
    line1 = line1.Replace(“margin-left:”, “margin-right:auto;margin-left:”);
    line1 = line1.Replace(“margin-temp:”, “margin-left:auto;margin-right:”);

    line1 = line1.Replace(“padding-right:”, “padding-temp:”);
    line1 = line1.Replace(“padding-left:”, “padding-right:auto;padding-left:”);
    line1 = line1.Replace(“padding-temp:”, “padding-left:auto;padding-right:”);

    line1 = Regex.Replace(line1, @”padding:(\d+)px (\d+)px (\d+)px (\d+)px”, “padding:$1px $4px $3px $2px”);
    sb.Append(line1);
    }
    }

    cssContent = @”body{direction:rtl}
    .ui-icon-arrow-r{background-position: -144px 50%;}
    ” + sb.ToString().Replace(“\n”, “”);
    StreamWriter wr = new StreamWriter(“jquery.mobile-1.3.0.min.rtl.css”, false, Encoding.GetEncoding(1255));
    wr.Write(cssContent);
    wr.Close();
    }
    }
    }

  6. One more correction to handle “ui-responsive-panel” :

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    using System.Text.RegularExpressions;

    namespace ConvertJqueryMobileToRtl
    {
    public partial class Form1 : Form
    {
    public Form1()
    {
    InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
    string cssContent = “”;

    StreamReader rd = new StreamReader(“jquery.mobile-1.3.0.min.css”, Encoding.GetEncoding(1255));
    cssContent = rd.ReadToEnd();
    rd.Close();
    cssContent = cssContent.Replace(“{“, “{\n”);
    cssContent = cssContent.Replace(“;”, “;\n”);
    cssContent = cssContent.Replace(“}”, “\n}\n\n”);

    string[] lines = cssContent.Split(‘\n’);
    StringBuilder sb = new StringBuilder();
    bool wastranslate3d = false;
    bool stopRTL = false;
    bool doMargin = false;
    foreach (string line in lines)
    {
    if (line.Contains(“-webkit-transform:translate3d(0,0,0)”))
    wastranslate3d = true;
    if (line.Contains(“.ui-panel-position-left”) && wastranslate3d)
    {
    stopRTL = true;
    }
    if (stopRTL)
    {
    if (line.Contains(“.ui-responsive-panel.”))
    doMargin = true;
    if (doMargin)
    {
    string line1 = line.Replace(“margin-right:”, “margin-temp:”);
    line1 = line1.Replace(“margin-left:”, “margin-right:”);
    line1 = line1.Replace(“margin-temp:”, “margin-left:”);
    sb.Append(line1);
    }
    else
    sb.Append(line);
    }
    else
    {
    string line1 = line.Replace(“right:”, “temp:”);
    line1 = line1.Replace(“right;”, “temp;”);
    line1 = line1.Replace(“left:”, “right:”);
    line1 = line1.Replace(“left;”, “right;”);
    line1 = line1.Replace(“temp:”, “left:”);
    line1 = line1.Replace(“temp;”, “left;”);

    line1 = line1.Replace(“margin-right:”, “margin-temp:”);
    line1 = line1.Replace(“margin-left:”, “margin-right:auto;margin-left:”);
    line1 = line1.Replace(“margin-temp:”, “margin-left:auto;margin-right:”);

    line1 = line1.Replace(“padding-right:”, “padding-temp:”);
    line1 = line1.Replace(“padding-left:”, “padding-right:auto;padding-left:”);
    line1 = line1.Replace(“padding-temp:”, “padding-left:auto;padding-right:”);

    line1 = Regex.Replace(line1, @”padding:(\d+)px (\d+)px (\d+)px (\d+)px”, “padding:$1px $4px $3px $2px”);
    sb.Append(line1);
    }
    }

    cssContent = @”body{direction:rtl}
    .ui-icon-arrow-r{background-position: -144px 50%;}
    ” + sb.ToString().Replace(“\n”, “”);
    StreamWriter wr = new StreamWriter(“jquery.mobile-1.3.0.min.rtl.css”, false, Encoding.GetEncoding(1255));
    wr.Write(cssContent);
    wr.Close();
    }
    }
    }

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s