Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Localization in MonoDroid

My app is localized using the standard .NET RESX methods (ie. String.fr.resx, Strings.de.resx etc.) works great under Windows Phone.

I am porting to Android using MonoDroid and I do not see the localized UI when I switch locales on the phone. If I rename the APK file to ZIP and open it I see that it has not packaged up the locale DLLs produced during the build (ie. the intermediate \.Resources.dll files are under the bin directory but are not packaged into the APK).

What am I missing? I have tried changing the build action on the RESX files from "Embedded Resource" to "Android Resource" and even "Android Asset" but to no avail.

Thanks in advance for any help!

Cheers Warren

like image 375
user1075034 Avatar asked Nov 05 '22 10:11

user1075034


1 Answers

I asked about this on the monodroid irc channel and the official answer was "not supported yet but we do have plans to do it".

You need to convert the resx files to android xml format (see below) and add them to your project as shown here: http://docs.xamarin.com/android/tutorials/Android_Resources/Part_5_-_Application_Localization_and_String_Resources

In my app (game) I needed to look up the localised strings by name. The code to do this was simple but not immediately obvious. Instead of using ResourceManager I swapped in this for android:

class AndroidResourcesProxy : Arands.Core.IResourcesProxy
{
    Context _context;

    public AndroidResourcesProxy(Context context)
    {
        _context = context;
    }

    public string GetString(string key)
    {
        int resId = _context.Resources.GetIdentifier(key, "string", _context.PackageName);
        return _context.Resources.GetString(resId);            
    }
}

Since I'm not a XSLT guru I made a command line program for converting resx to Android string XML files:

/// <summary>
/// Conerts localisation resx string files into the android xml format
/// </summary>
class Program
{
    static void Main(string[] args)
    {
        string inFile = args[0];
        XmlDocument inDoc = new XmlDocument();
        using (XmlTextReader reader = new XmlTextReader(inFile))
        {
            inDoc.Load(reader);
        }

        string outFile = Path.Combine(Path.GetDirectoryName(inFile), Path.GetFileNameWithoutExtension(inFile)) + ".xml";
        XmlDocument outDoc = new XmlDocument();
        outDoc.AppendChild(outDoc.CreateXmlDeclaration("1.0", "utf-8", null));

        XmlElement resElem = outDoc.CreateElement("resources");
        outDoc.AppendChild(resElem);

        XmlNodeList stringNodes = inDoc.SelectNodes("root/data");
        foreach (XmlNode n in stringNodes)
        {
            string key = n.Attributes["name"].Value;
            string val = n.SelectSingleNode("value").InnerText;

            XmlElement stringElem = outDoc.CreateElement("string");
            XmlAttribute nameAttrib = outDoc.CreateAttribute("name");
            nameAttrib.Value = key;
            stringElem.Attributes.Append(nameAttrib);
            stringElem.InnerText = val;

            resElem.AppendChild(stringElem);
        }

        XmlWriterSettings xws = new XmlWriterSettings();
        xws.Encoding = Encoding.UTF8;
        xws.Indent = true;
        xws.NewLineChars = "\n";

        using (StreamWriter sr = new StreamWriter(outFile))
        {
            using (XmlWriter writer = XmlWriter.Create(sr, xws))
            {
                outDoc.Save(writer);
            }
        }
    }
}
like image 110
Aranda Avatar answered Nov 17 '22 12:11

Aranda