Example #1
0
 public void AddDictionary(BamlLocalizationDictionary dictionary)
 {
     if (dictionary != null)
     {
         dictionariesList.Add(dictionary);
     }
 }
Example #2
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="reader">resoure text reader that reads CSV or a tab-separated txt file</param>
        internal TranslationDictionariesReader(IBamlResourceReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            // hash key is case insensitive strings
            table = new Hashtable();

            // we read each Row
            while (reader.MoveNext())
            {
                // get the dictionary
                BamlLocalizationDictionary dictionary = this[reader.CurrentBamlName];
                if (dictionary == null)
                {
                    // we create one if it is not there yet.
                    dictionary = new BamlLocalizationDictionary();
                    this[reader.CurrentBamlName] = dictionary;
                }

                // at this point, we are good.
                // add to the dictionary.
                dictionary.Add(reader.CurrentResourceKey, reader.CurrentResource);
            }
        }
Example #3
0
        /// <summary>
        /// Write the localizable key-value pairs
        /// </summary>
        /// <param name="options"></param>
        internal static void Write(LocBamlOptions options)
        {
            InputBamlStreamList bamlStreamList = new InputBamlStreamList(options);

            using (ITranslationWriter writer = options.GetTranslationWriter())
            {
                options.WriteLine(StringLoader.Get("WriteBamlValues"));
                for (int i = 0; i < bamlStreamList.Count; i++)
                {
                    options.Write("    ");
                    options.Write(StringLoader.Get("ProcessingBaml", bamlStreamList[i].Name));

                    // Search for comment file in the same directory. The comment file has the extension to be
                    // "loc".
                    string     commentFile   = Path.ChangeExtension(bamlStreamList[i].Name, "loc");
                    TextReader commentStream = null;

                    try
                    {
                        if (File.Exists(commentFile))
                        {
                            commentStream = new StreamReader(commentFile);
                        }

                        // create the baml localizer
                        BamlLocalizer mgr = new BamlLocalizer(
                            bamlStreamList[i].Stream,
                            new BamlLocalizabilityByReflection(options.Assemblies),
                            commentStream
                            );

                        // extract localizable resource from the baml stream
                        BamlLocalizationDictionary dict = mgr.ExtractResources();

                        // write out each resource
                        foreach (DictionaryEntry entry in dict)
                        {
                            BamlLocalizableResourceKey key      = (BamlLocalizableResourceKey)entry.Key;
                            BamlLocalizableResource    resource = (BamlLocalizableResource)entry.Value;

                            writer.WriteResource(bamlStreamList[i].Name, LocBamlConst.ResourceKeyToString(key), resource);
                        }

                        options.WriteLine(StringLoader.Get("Done"));
                    }
                    finally
                    {
                        if (commentStream != null)
                        {
                            commentStream.Close();
                        }
                    }
                }

                // close all the baml input streams, output stream is closed by writer.
                bamlStreamList.Close();
            }
        }
        //-----------------------------
        // internal methods
        //-----------------------------

        internal static void UpdateTree(
            BamlTree tree,
            BamlTreeMap treeMap,
            BamlLocalizationDictionary dictionary
            )
        {
            Debug.Assert(tree != null && tree.Root != null, "Empty Tree!");
            Debug.Assert(treeMap != null, "Empty map!");
            Debug.Assert(dictionary != null, "Empty dictionary");

            // no changes to do to the tree.
            if (dictionary.Count <= 0)
            {
                return;
            }

            // create a tree map to be used for update
            BamlTreeUpdateMap updateMap = new BamlTreeUpdateMap(treeMap, tree);

            //
            // a) Create baml tree nodes for missing child place holders and properties.
            //    Translations may require new nodes to be constructed. For example
            //    translation contains new child place holders
            //
            CreateMissingBamlTreeNode(dictionary, updateMap);


            //
            // b) Look through each translation and make modification to the tree
            //    At this step, new nodes are linked to the tree if applicable.
            //
            BamlLocalizationDictionaryEnumerator enumerator = dictionary.GetEnumerator();
            ArrayList deferredResources = new ArrayList();

            while (enumerator.MoveNext())
            {
                if (!ApplyChangeToBamlTree(enumerator.Key, enumerator.Value, updateMap))
                {
                    deferredResources.Add(enumerator.Entry);
                }
            }

            //
            // c) Hook up the property nodes that aren't hooked up yet
            //    Formatting tags inserted in the translation will only be created the
            //    previous step. Hook up properties to those nodes now if applicable
            //
            for (int i = 0; i < deferredResources.Count; i++)
            {
                DictionaryEntry entry = (DictionaryEntry)deferredResources[i];
                ApplyChangeToBamlTree(
                    (BamlLocalizableResourceKey)entry.Key,
                    (BamlLocalizableResource)entry.Value,
                    updateMap
                    );
            }
        }
        internal TranslationDictionariesReader(List <BamlString> bamlStrings)
        {
            // hash key is case insensitive strings
            _table = new Hashtable();

            // we read each Row
            int rowNumber = 0;

            foreach (BamlString bamlString in bamlStrings)
            {
                rowNumber++;

                // field #1 is the baml name.
                string bamlName = bamlString.BamlFile;

                // it can't be null
                if (bamlName == null)
                {
                    throw new ApplicationException(StringLoader.Get("EmptyRowEncountered"));
                }

                // field #2: key to the localizable resource
                string key = bamlString.ResourceKey;
                if (key == null)
                {
                    throw new ApplicationException(StringLoader.Get("NullBamlKeyNameInRow"));
                }

                BamlLocalizableResourceKey resourceKey = LocBamlConst.StringToResourceKey(key);

                // get the dictionary
                BamlLocalizationDictionary dictionary = this[bamlName];
                if (dictionary == null)
                {
                    // we create one if it is not there yet.
                    dictionary     = new BamlLocalizationDictionary();
                    this[bamlName] = dictionary;
                }

                BamlLocalizableResource resource;

                // the rest of the fields are either all null,
                // or all non-null. If all null, it means the resource entry is deleted.

                resource            = new BamlLocalizableResource();
                resource.Category   = bamlString.Category;
                resource.Readable   = (bool)BoolTypeConverter.ConvertFrom(bamlString.Readability);
                resource.Modifiable = (bool)BoolTypeConverter.ConvertFrom(bamlString.Modifiable);
                resource.Comments   = bamlString.Comments;
                // in case content being the last column, consider null as empty.
                resource.Content = bamlString.Content ?? string.Empty;

                // at this point, we are good.
                // add to the dictionary.
                dictionary.Add(resourceKey, resource);
            }
        }
Example #6
0
        private void GenerateBamlStream(Stream input, Stream output, Dictionaries curDictionaries)
        {
            string     commentFile   = Path.ChangeExtension(options.Input, "loc");
            TextReader commentStream = null;

            try
            {
                if (File.Exists(commentFile))
                {
                    commentStream = new StreamReader(commentFile);
                }

                // create a localizabilty resolver based on reflection
                var localizabilityReflector =
                    new BamlLocalizabilityByReflection(options.Assemblies);

                // create baml localizer
                var mgr = new BamlLocalizer(
                    input,
                    localizabilityReflector,
                    commentStream
                    );

                // get the resources
                var source       = mgr.ExtractResources();
                var translations = new BamlLocalizationDictionary();

                foreach (DictionaryEntry entry in source)
                {
                    var key = (BamlLocalizableResourceKey)entry.Key;
                    var translatedResource = curDictionaries.FindCorrespondence(key);
                    if (translatedResource != null)
                    {
                        string translatedContent = translatedResource.Content;

                        if (!String.IsNullOrEmpty(translatedContent))
                        {
                            var curResource = (BamlLocalizableResource)entry.Value;
                            if (curResource.Content != translatedContent)
                            {
                                translations.Add(key, translatedResource);
                            }
                        }
                    }
                }

                // update baml
                mgr.UpdateBaml(output, translations);
            }
            finally
            {
                if (commentStream != null)
                {
                    commentStream.Close();
                }
            }
        }
Example #7
0
        internal static List <BamlString> ExtractBamlStrings(Assembly assembly)
        {
            InputBamlStreamList bamlStreamList = new InputBamlStreamList(assembly);

            List <BamlString> resultingList = new List <BamlString>();

            for (int i = 0; i < bamlStreamList.Count; i++)
            {
                // Search for comment file in the same directory. The comment file has the extension to be
                // "loc".
//                string commentFile = Path.ChangeExtension(bamlStreamList[i].Name, "loc");
                TextReader commentStream = null;

                try
                {
                    //if (File.Exists(commentFile))
                    //{
                    //    commentStream = new StreamReader(commentFile);
                    //}

                    // create the baml localizer
                    BamlLocalizer mgr = new BamlLocalizer(
                        bamlStreamList[i].Stream,
                        new BamlLocalizabilityByReflection(new Assembly[] { assembly }),
                        commentStream
                        );

                    // extract localizable resource from the baml stream
                    BamlLocalizationDictionary dict = mgr.ExtractResources();

                    // write out each resource
                    foreach (DictionaryEntry entry in dict)
                    {
                        BamlLocalizableResourceKey key      = (BamlLocalizableResourceKey)entry.Key;
                        BamlLocalizableResource    resource = (BamlLocalizableResource)entry.Value;

                        resultingList.Add(new BamlString(bamlStreamList[i].Name, LocBamlConst.ResourceKeyToString(key), resource));
                    }
                }
                finally
                {
                    if (commentStream != null)
                    {
                        commentStream.Close();
                    }
                }
            }

            // close all the baml input streams, output stream is closed by writer.
            bamlStreamList.Close();

            // options.WriteLine(StringLoader.Get("Done"));


            return(resultingList);
        }
        private static string GenerateBamlStream(Stream input, Stream output, BamlLocalizationDictionary dictionary, LocBamlOptions options)
        {
            string     commentFile   = Path.ChangeExtension(options.Input, "loc");
            TextReader commentStream = null;

            try
            {
                if (File.Exists(commentFile))
                {
                    commentStream = new StreamReader(commentFile);
                }

                // create a localizabilty resolver based on reflection
                BamlLocalizabilityByReflection localizabilityReflector =
                    new BamlLocalizabilityByReflection(options.Assemblies);

                // create baml localizer
                BamlLocalizer mgr = new BamlLocalizer(
                    input,
                    localizabilityReflector,
                    commentStream
                    );

                // get the resources
                BamlLocalizationDictionary source       = mgr.ExtractResources();
                BamlLocalizationDictionary translations = new BamlLocalizationDictionary();

                foreach (DictionaryEntry entry in dictionary)
                {
                    BamlLocalizableResourceKey key = (BamlLocalizableResourceKey)entry.Key;
                    // filter out unchanged items
                    if (!source.Contains(key) ||
                        entry.Value == null ||
                        source[key].Content != ((BamlLocalizableResource)entry.Value).Content)
                    {
                        translations.Add(key, (BamlLocalizableResource)entry.Value);
                    }
                }

                // update baml
                mgr.UpdateBaml(output, translations);
            }
            catch (Exception ex)
            {
                return(ex.Message);
            }
            finally
            {
                if (commentStream != null)
                {
                    commentStream.Close();
                }
            }
            return(null);
        }
Example #9
0
    public static void Main(string[] args)
    {
        if (args.Length != 1)
        {
            Console.WriteLine("this.exe [resource.dll]");
            return;
        }

        Assembly assembly = Assembly.LoadFrom(args[0]);

        foreach (string resourceName in assembly.GetManifestResourceNames())
        {
            Stream resourceStream = assembly.GetManifestResourceStream(resourceName);
            using (ResourceReader reader = new ResourceReader(resourceStream))
            {
                foreach (DictionaryEntry entry in reader)
                {
                    string name = entry.Key as string;

                    if (Path.GetExtension(name).ToUpperInvariant() == ".BAML")
                    {
                        Console.WriteLine("Processing baml {0}", name);

                        // <Snippet1>

                        // Obtain the BAML stream.
                        Stream source = entry.Value as Stream;

                        // Create a BamlLocalizer on the stream.
                        BamlLocalizer localizer = new BamlLocalizer(source);
                        BamlLocalizationDictionary resources = localizer.ExtractResources();

                        // Write out all the localizable resources in the BAML.
                        foreach (DictionaryEntry resourceEntry in resources)
                        {
                            BamlLocalizableResourceKey key   = resourceEntry.Key as BamlLocalizableResourceKey;
                            BamlLocalizableResource    value = resourceEntry.Value as BamlLocalizableResource;
                            Console.WriteLine(
                                "    {0}.{1}.{2} = {3}",
                                key.Uid,
                                key.ClassName,
                                key.PropertyName,
                                value.Content
                                );
                        }
                        // </Snippet1>

                        Console.WriteLine("Done");
                    }
                }
            }
        }
    }
        internal TranslationDictionariesReader(XliffObject xliff)
        {
            // hash key is case insensitive strings
            _table = new Hashtable();

            foreach (File file in xliff.Files)
            {
                string bamlName = file.Original;

                // get the dictionary
                BamlLocalizationDictionary dictionary = this[bamlName];
                if (dictionary == null)
                {
                    // we create one if it is not there yet.
                    dictionary     = new BamlLocalizationDictionary();
                    this[bamlName] = dictionary;
                }

                Body body = file.Body;
                // There should only be one group, but go through any that exist for good measure
                foreach (Group group in body.Groups)
                {
                    foreach (TranslationUnit transUnit in group.TranslationUnits)
                    {
                        string key = transUnit.Id;
                        BamlLocalizableResourceKey resourceKey = LocBamlConst.StringToResourceKey(key);
                        BamlLocalizableResource    resource    = new BamlLocalizableResource();
                        resource.Category = (LocalizationCategory)StringCatConverter.ConvertFrom(transUnit.ResourceType);

                        /*
                         * resource.Readable = (bool)BoolTypeConverter.ConvertFrom(reader.GetColumn(3));
                         * resource.Modifiable = (bool)BoolTypeConverter.ConvertFrom(reader.GetColumn(4));
                         */
                        Note comment = transUnit.Notes.FirstOrDefault(n => n.From == "MultilingualBuild");
                        if (comment != null)
                        {
                            resource.Comments = comment.Text;
                        }
                        resource.Content = transUnit.Target.Content ?? string.Empty;

                        dictionary.Add(resourceKey, resource);
                    }
                }
            }
        }
        // Token: 0x06006EAB RID: 28331 RVA: 0x001FC55C File Offset: 0x001FA75C
        private static void CreateMissingBamlTreeNode(BamlLocalizationDictionary dictionary, BamlTreeUpdater.BamlTreeUpdateMap treeMap)
        {
            BamlLocalizationDictionaryEnumerator enumerator = dictionary.GetEnumerator();

            while (enumerator.MoveNext())
            {
                BamlLocalizableResourceKey key   = enumerator.Key;
                BamlLocalizableResource    value = enumerator.Value;
                if (treeMap.MapKeyToBamlTreeNode(key) == null)
                {
                    if (key.PropertyName == "$Content")
                    {
                        if (treeMap.MapUidToBamlTreeElementNode(key.Uid) == null)
                        {
                            BamlStartElementNode bamlStartElementNode = new BamlStartElementNode(treeMap.Resolver.ResolveAssemblyFromClass(key.ClassName), key.ClassName, false, false);
                            bamlStartElementNode.AddChild(new BamlDefAttributeNode("Uid", key.Uid));
                            BamlTreeUpdater.TryAddContentPropertyToNewElement(treeMap, bamlStartElementNode);
                            bamlStartElementNode.AddChild(new BamlEndElementNode());
                            treeMap.AddBamlTreeNode(key.Uid, key, bamlStartElementNode);
                        }
                    }
                    else
                    {
                        BamlTreeNode node;
                        if (key.PropertyName == "$LiteralContent")
                        {
                            node = new BamlLiteralContentNode(value.Content);
                        }
                        else
                        {
                            node = new BamlPropertyNode(treeMap.Resolver.ResolveAssemblyFromClass(key.ClassName), key.ClassName, key.PropertyName, value.Content, BamlAttributeUsage.Default);
                        }
                        treeMap.AddBamlTreeNode(null, key, node);
                    }
                }
            }
        }
        // Token: 0x06006EAA RID: 28330 RVA: 0x001FC4B8 File Offset: 0x001FA6B8
        internal static void UpdateTree(BamlTree tree, BamlTreeMap treeMap, BamlLocalizationDictionary dictionary)
        {
            if (dictionary.Count <= 0)
            {
                return;
            }
            BamlTreeUpdater.BamlTreeUpdateMap treeMap2 = new BamlTreeUpdater.BamlTreeUpdateMap(treeMap, tree);
            BamlTreeUpdater.CreateMissingBamlTreeNode(dictionary, treeMap2);
            BamlLocalizationDictionaryEnumerator enumerator = dictionary.GetEnumerator();
            ArrayList arrayList = new ArrayList();

            while (enumerator.MoveNext())
            {
                if (!BamlTreeUpdater.ApplyChangeToBamlTree(enumerator.Key, enumerator.Value, treeMap2))
                {
                    arrayList.Add(enumerator.Entry);
                }
            }
            for (int i = 0; i < arrayList.Count; i++)
            {
                DictionaryEntry dictionaryEntry = (DictionaryEntry)arrayList[i];
                BamlTreeUpdater.ApplyChangeToBamlTree((BamlLocalizableResourceKey)dictionaryEntry.Key, (BamlLocalizableResource)dictionaryEntry.Value, treeMap2);
            }
        }
Example #13
0
 public BamlLocalizableResourceKey FindCorrespondenceKey(BamlLocalizableResourceKey key, BamlLocalizationDictionary dictionary)
 {
     return(key);
 }
Example #14
0
 public BamlLocalizableResource FindCorrespondence(BamlLocalizableResourceKey key, BamlLocalizationDictionary dictionary)
 {
     if (dictionary.Contains(key))
     {
         return(dictionary[key]);
     }
     return(null);
 }
Example #15
0
        //--------------------------------------
        // Private methods
        //--------------------------------------
        // construct the maps for enumeration
        internal void EnsureMap()
        {
            if (_localizableResources != null)
            {
                return; // map is already created.
            }
            // create the table based on the treesize passed in
            // the hashtable is for look-up during update
            _resolver.InitLocalizabilityCache();
            _keyToBamlNodeIndexMap = new Hashtable(_tree.Size);
            _uidToBamlNodeIndexMap = new Hashtable(_tree.Size / 2);
            _localizableResources  = new BamlLocalizationDictionary();

            for (int i = 0; i < _tree.Size; i++)
            {
                BamlTreeNode currentNode = _tree[i];

                // a node may be marked as unidentifiable if it or its parent has a duplicate uid.
                if (currentNode.Unidentifiable)
                {
                    continue;                             // skip unidentifiable nodes
                }
                if (currentNode.NodeType == BamlNodeType.StartElement)
                {
                    // remember classes encountered in this baml
                    BamlStartElementNode elementNode = (BamlStartElementNode)currentNode;
                    _resolver.AddClassAndAssembly(elementNode.TypeFullName, elementNode.AssemblyName);
                }

                // find the Uid of the current node
                BamlLocalizableResourceKey key = GetKey(currentNode);

                if (key != null)
                {
                    if (currentNode.NodeType == BamlNodeType.StartElement)
                    {
                        // store uid mapping to the corresponding element node
                        if (_uidToBamlNodeIndexMap.ContainsKey(key.Uid))
                        {
                            _resolver.RaiseErrorNotifyEvent(
                                new BamlLocalizerErrorNotifyEventArgs(
                                    key,
                                    BamlLocalizerError.DuplicateUid
                                    )
                                );

                            // Mark this element and its properties unidentifiable.
                            currentNode.Unidentifiable = true;
                            if (currentNode.Children != null)
                            {
                                foreach (BamlTreeNode child in currentNode.Children)
                                {
                                    if (child.NodeType != BamlNodeType.StartElement)
                                    {
                                        child.Unidentifiable = true;
                                    }
                                }
                            }

                            continue; // skip the duplicate node
                        }
                        else
                        {
                            _uidToBamlNodeIndexMap.Add(key.Uid, i);
                        }
                    }

                    _keyToBamlNodeIndexMap.Add(key, i);

                    if (_localizableResources.RootElementKey == null &&
                        currentNode.NodeType == BamlNodeType.StartElement &&
                        currentNode.Parent != null &&
                        currentNode.Parent.NodeType == BamlNodeType.StartDocument)
                    {
                        // remember the key to the root element so that
                        // users can further add modifications to the root that would have a global impact.
                        // such as FlowDirection or CultureInfo
                        _localizableResources.SetRootElementKey(key);
                    }

                    // create the resource and add to the dictionary
                    BamlLocalizableResource resource = _localizableResourceBuilder.BuildFromNode(key, currentNode);

                    if (resource != null)
                    {
                        _localizableResources.Add(key, resource);
                    }
                }
            }

            _resolver.ReleaseLocalizabilityCache();
        }
        internal static void GenerateAssembly(ResourceGenerationOptions options)
        {
            TranslationDictionariesReader dictionaries = new TranslationDictionariesReader(options.BamlStrings);

            string sourceAssemblyFullName  = options.AssemblyFileName;                           // source assembly full path
            string outputAssemblyLocalName = System.IO.Path.GetFileName(options.OutputFileName); // output assembly name
            string moduleLocalName         = GetAssemblyModuleLocalName(
                options.CultureInfo,
                System.IO.Path.GetFileName(outputAssemblyLocalName));                                     // the module name within the assmbly

            // get the source assembly
            Assembly    sourceAssembly = options.SourceAssembly;
            CultureInfo cultureInfo    = options.CultureInfo;

            // obtain the assembly name
            AssemblyName targetAssemblyNameObj = sourceAssembly.GetName();

            // store the culture info of the source assembly
            CultureInfo srcCultureInfo = targetAssemblyNameObj.CultureInfo;

            // update it to use it for target assembly
            targetAssemblyNameObj.Name        = Path.GetFileNameWithoutExtension(outputAssemblyLocalName);
            targetAssemblyNameObj.CultureInfo = cultureInfo;

            // we get a assembly builder
            AssemblyBuilder targetAssemblyBuilder = options.AppDomain.DefineDynamicAssembly(
                targetAssemblyNameObj,                                  // name of the assembly
                AssemblyBuilderAccess.RunAndSave,                       // access rights
                System.IO.Path.GetDirectoryName(options.OutputFileName) // storage dir
                );

            // we create a module builder for embeded resource modules
            ModuleBuilder moduleBuilder = targetAssemblyBuilder.DefineDynamicModule(
                moduleLocalName,
                outputAssemblyLocalName
                );

            //options.WriteLine(StringLoader.Get("GenerateAssembly"));

            // now for each resource in the assembly
            foreach (string resourceName in sourceAssembly.GetManifestResourceNames())
            {
                // get the resource location for the resource
                ResourceLocation resourceLocation = sourceAssembly.GetManifestResourceInfo(resourceName).ResourceLocation;

                // if this resource is in another assemlby, we will skip it
                if ((resourceLocation & ResourceLocation.ContainedInAnotherAssembly) != 0)
                {
                    continue;   // in resource assembly, we don't have resource that is contained in another assembly
                }

                // gets the neutral resource name, giving it the source culture info
                string neutralResourceName = GetNeutralResModuleName(resourceName, srcCultureInfo);

                // gets the target resource name, by giving it the target culture info
                string targetResourceName = GetCultureSpecificResourceName(neutralResourceName, cultureInfo);

                // resource stream
                Stream resourceStream = sourceAssembly.GetManifestResourceStream(resourceName);

                // see if it is a .resources
                if (neutralResourceName.ToLower(CultureInfo.InvariantCulture).EndsWith(".resources"))
                {
                    // now we think we have resource stream
                    // get the resource writer
                    IResourceWriter writer;
                    // check if it is a embeded assembly
                    if ((resourceLocation & ResourceLocation.Embedded) != 0)
                    {
                        // gets the resource writer from the module builder
                        writer = moduleBuilder.DefineResource(
                            targetResourceName,         // resource name
                            targetResourceName,         // resource description
                            ResourceAttributes.Public   // visibilty of this resource to other assembly
                            );
                    }
                    else
                    {
                        // it is a standalone resource, we get the resource writer from the assembly builder
                        writer = targetAssemblyBuilder.DefineResource(
                            targetResourceName,         // resource name
                            targetResourceName,         // description
                            targetResourceName,         // file name to save to
                            ResourceAttributes.Public   // visibility of this resource to other assembly
                            );
                    }

                    // get the resource reader
                    IResourceReader reader = new ResourceReader(resourceStream);

                    // generate the resources
                    GenerateResourceStream(options, resourceName, reader, writer, dictionaries);

                    // we don't call writer.Generate() or writer.Close() here
                    // because the AssemblyBuilder will call them when we call Save() on it.
                }
                else
                {
                    // else it is a stand alone untyped manifest resources.
                    string extension = Path.GetExtension(targetResourceName);

                    string fullFileName = Path.Combine(
                        System.IO.Path.GetDirectoryName(options.AssemblyFileName),
                        targetResourceName);

                    // check if it is a .baml, case-insensitive
                    if (string.Compare(extension, ".baml", true, CultureInfo.InvariantCulture) == 0)
                    {
                        // try to localized the the baml
                        // find the resource dictionary
                        BamlLocalizationDictionary dictionary = dictionaries[resourceName];

                        // if it is null, just create an empty dictionary.
                        if (dictionary != null)
                        {
                            // it is a baml stream
                            using (Stream output = File.OpenWrite(fullFileName))
                            {
                                options.Write("    ");
                                options.WriteLine(StringLoader.Get("GenerateStandaloneBaml", fullFileName));
                                GenerateBamlStream(resourceStream, output, dictionary, options);
                                options.WriteLine(StringLoader.Get("Done"));
                            }
                        }
                        else
                        {
                            // can't find localization of it, just copy it
                            GenerateStandaloneResource(fullFileName, resourceStream);
                        }
                    }
                    else
                    {
                        // it is an untyped resource stream, just copy it
                        GenerateStandaloneResource(fullFileName, resourceStream);
                    }

                    // now add this resource file into the assembly
                    targetAssemblyBuilder.AddResourceFile(
                        targetResourceName,           // resource name
                        targetResourceName,           // file name
                        ResourceAttributes.Public     // visibility of the resource to other assembly
                        );
                }
            }

            // at the end, generate the assembly
            targetAssemblyBuilder.Save(outputAssemblyLocalName);
            options.WriteLine(StringLoader.Get("DoneGeneratingAssembly"));
        }
        private static void GenerateResourceStream(
            ResourceGenerationOptions options,              // options from the command line
            string resourceName,                            // the name of the .resources file
            IResourceReader reader,                         // the reader for the .resources
            IResourceWriter writer,                         // the writer for the output .resources
            TranslationDictionariesReader dictionaries      // the translations
            )
        {
            //options.WriteLine(StringLoader.Get("GenerateResource", resourceName));
            // enumerate through each resource and generate it
            foreach (DictionaryEntry entry in reader)
            {
                string name          = entry.Key as string;
                object resourceValue = null;

                // See if it looks like a Baml resource
                if (BamlStream.IsResourceEntryBamlStream(name, entry.Value))
                {
                    Stream targetStream = null;
                    //                    options.Write("    ");
                    //options.Write(StringLoader.Get("GenerateBaml", name));

                    // grab the localizations available for this Baml
                    string bamlName = BamlStream.CombineBamlStreamName(resourceName, name);
                    BamlLocalizationDictionary localizations = dictionaries[bamlName];
                    if (localizations != null)
                    {
                        targetStream = new MemoryStream();

                        // generate into a new Baml stream
                        GenerateBamlStream(
                            (Stream)entry.Value,
                            targetStream,
                            localizations,
                            options
                            );
                    }

                    options.WriteLine(StringLoader.Get("Done"));

                    // sets the generated object to be the generated baml stream
                    resourceValue = targetStream;
                }

                if (resourceValue == null)
                {
                    //
                    // The stream is not localized as Baml yet, so we will make a copy of this item into
                    // the localized resources
                    //

                    // We will add the value as is if it is serializable. Otherwise, make a copy
                    resourceValue = entry.Value;

                    object[] serializableAttributes = resourceValue.GetType().GetCustomAttributes(typeof(SerializableAttribute), true);
                    if (serializableAttributes.Length == 0)
                    {
                        // The item returned from resource reader is not serializable
                        // If it is Stream, we can wrap all the values in a MemoryStream and
                        // add to the resource. Otherwise, we had to skip this resource.
                        Stream resourceStream = resourceValue as Stream;
                        if (resourceStream != null)
                        {
                            Stream targetStream = new MemoryStream();
                            byte[] buffer       = new byte[resourceStream.Length];
                            resourceStream.Read(buffer, 0, buffer.Length);
                            targetStream  = new MemoryStream(buffer);
                            resourceValue = targetStream;
                        }
                    }
                }

                if (resourceValue != null)
                {
                    writer.AddResource(name, resourceValue);
                }
            }
        }
Example #18
0
        //--------------------------------------------------
        // The function follows Managed code parser
        // implementation. in the future, maybe they should
        // share the same code
        //--------------------------------------------------
        private static void GenerateAssembly(LocBamlOptions options, TranslationDictionariesReader dictionaries)
        {
            // there are many names to be used when generating an assembly
            string sourceAssemblyFullName  = options.Input;                                                // source assembly full path
            string outputAssemblyDir       = options.Output;                                               // output assembly directory
            string outputAssemblyLocalName = GetOutputFileName(options);                                   // output assembly name
            string moduleLocalName         = GetAssemblyModuleLocalName(options, outputAssemblyLocalName); // the module name within the assmbly

            // get the source assembly
            Assembly srcAsm = Assembly.LoadFrom(sourceAssemblyFullName);

            // obtain the assembly name
            AssemblyName targetAssemblyNameObj = srcAsm.GetName();

            // store the culture info of the source assembly
            CultureInfo srcCultureInfo = targetAssemblyNameObj.CultureInfo;

            // update it to use it for target assembly
            targetAssemblyNameObj.Name        = Path.GetFileNameWithoutExtension(outputAssemblyLocalName);
            targetAssemblyNameObj.CultureInfo = options.CultureInfo;

            // we get a assembly builder
            AssemblyBuilder targetAssemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(
                targetAssemblyNameObj,                  // name of the assembly
                AssemblyBuilderAccess.RunAndSave,       // access rights
                outputAssemblyDir                       // storage dir
                );

            // Add assembly info, trying to preserver original values as close as possible
            Action <Type, string> AddCustomStringAttribute = (Type type, string content) =>
            {
                if (string.IsNullOrEmpty(content))
                {
                    return;
                }
                ConstructorInfo ctor = type.GetConstructor(new Type[] { typeof(string) });
                targetAssemblyBuilder.SetCustomAttribute(new CustomAttributeBuilder(ctor, new object[] { content }));
            };
            bool hasInformationalVersionAttr = false;

            object[] attrs = srcAsm.GetCustomAttributes(false);
            foreach (var attr in attrs)
            {
                if (attr is AssemblyCompanyAttribute cmp)
                {
                    AddCustomStringAttribute(attr.GetType(), cmp.Company); continue;
                }
                if (attr is AssemblyCopyrightAttribute copy)
                {
                    AddCustomStringAttribute(attr.GetType(), copy.Copyright); continue;
                }
                if (attr is AssemblyDescriptionAttribute da)
                {
                    AddCustomStringAttribute(attr.GetType(), da.Description); continue;
                }
                if (attr is AssemblyFileVersionAttribute fva)
                {
                    AddCustomStringAttribute(attr.GetType(), fva.Version);
                    if (!hasInformationalVersionAttr)
                    {
                        // Also set AssemblyInformationalVersionAttribute, if not set already.
                        // The unmanaged ProductVersion is taken from that attribute.
                        AddCustomStringAttribute(typeof(AssemblyInformationalVersionAttribute), fva.Version);
                    }
                    continue;
                }
                if (attr is AssemblyInformationalVersionAttribute iva)
                {
                    AddCustomStringAttribute(attr.GetType(), iva.InformationalVersion);
                    hasInformationalVersionAttr = true;
                    continue;
                }
                if (attr is AssemblyProductAttribute pa)
                {
                    AddCustomStringAttribute(attr.GetType(), pa.Product); continue;
                }
                if (attr is AssemblyTitleAttribute ta)
                {
                    AddCustomStringAttribute(attr.GetType(), ta.Title); continue;
                }
                if (attr is AssemblyTrademarkAttribute tm)
                {
                    AddCustomStringAttribute(attr.GetType(), tm.Trademark); continue;
                }
                if (attr is AssemblyVersionAttribute va)
                {
                    AddCustomStringAttribute(attr.GetType(), va.Version); continue;
                }
            }
            targetAssemblyBuilder.DefineVersionInfoResource();

            // we create a module builder for embeded resource modules
            ModuleBuilder moduleBuilder = targetAssemblyBuilder.DefineDynamicModule(
                moduleLocalName,
                outputAssemblyLocalName
                );

            options.WriteLine(StringLoader.Get("GenerateAssembly"));

            // now for each resource in the assembly
            foreach (string resourceName in srcAsm.GetManifestResourceNames())
            {
                // get the resource location for the resource
                ResourceLocation resourceLocation = srcAsm.GetManifestResourceInfo(resourceName).ResourceLocation;

                // if this resource is in another assemlby, we will skip it
                if ((resourceLocation & ResourceLocation.ContainedInAnotherAssembly) != 0)
                {
                    continue;   // in resource assembly, we don't have resource that is contained in another assembly
                }

                // gets the neutral resource name, giving it the source culture info
                string neutralResourceName = GetNeutralResModuleName(resourceName, srcCultureInfo);

                // gets the target resource name, by giving it the target culture info
                string targetResourceName = GetCultureSpecificResourceName(neutralResourceName, options.CultureInfo);

                // resource stream
                Stream resourceStream = srcAsm.GetManifestResourceStream(resourceName);

                // see if it is a .resources
                if (neutralResourceName.ToLower(CultureInfo.InvariantCulture).EndsWith(".resources"))
                {
                    // now we think we have resource stream
                    // get the resource writer
                    IResourceWriter writer;
                    // check if it is a embeded assembly
                    if ((resourceLocation & ResourceLocation.Embedded) != 0)
                    {
                        // gets the resource writer from the module builder
                        writer = moduleBuilder.DefineResource(
                            targetResourceName,         // resource name
                            targetResourceName,         // resource description
                            ResourceAttributes.Public   // visibilty of this resource to other assembly
                            );
                    }
                    else
                    {
                        // it is a standalone resource, we get the resource writer from the assembly builder
                        writer = targetAssemblyBuilder.DefineResource(
                            targetResourceName,         // resource name
                            targetResourceName,         // description
                            targetResourceName,         // file name to save to
                            ResourceAttributes.Public   // visibility of this resource to other assembly
                            );
                    }

                    // get the resource reader
                    IResourceReader reader = new ResourceReader(resourceStream);

                    // generate the resources
                    GenerateResourceStream(options, resourceName, reader, writer, dictionaries);

                    // we don't call writer.Generate() or writer.Close() here
                    // because the AssemblyBuilder will call them when we call Save() on it.
                }
                else
                {
                    // else it is a stand alone untyped manifest resources.
                    string extension = Path.GetExtension(targetResourceName);

                    string fullFileName = Path.Combine(outputAssemblyDir, targetResourceName);

                    // check if it is a .baml, case-insensitive
                    if (string.Compare(extension, ".baml", true, CultureInfo.InvariantCulture) == 0)
                    {
                        // try to localized the the baml
                        // find the resource dictionary
                        BamlLocalizationDictionary dictionary = dictionaries[resourceName];

                        // if it is null, just create an empty dictionary.
                        if (dictionary != null)
                        {
                            // it is a baml stream
                            using (Stream output = File.OpenWrite(fullFileName))
                            {
                                options.Write("    ");
                                options.WriteLine(StringLoader.Get("GenerateStandaloneBaml", fullFileName));
                                GenerateBamlStream(resourceStream, output, dictionary, options);
                                options.WriteLine(StringLoader.Get("Done"));
                            }
                        }
                        else
                        {
                            // can't find localization of it, just copy it
                            GenerateStandaloneResource(fullFileName, resourceStream);
                        }
                    }
                    else
                    {
                        // it is an untyped resource stream, just copy it
                        GenerateStandaloneResource(fullFileName, resourceStream);
                    }

                    // now add this resource file into the assembly
                    targetAssemblyBuilder.AddResourceFile(
                        targetResourceName,           // resource name
                        targetResourceName,           // file name
                        ResourceAttributes.Public     // visibility of the resource to other assembly
                        );
                }
            }

            // at the end, generate the assembly
            targetAssemblyBuilder.Save(outputAssemblyLocalName);
            options.WriteLine(StringLoader.Get("DoneGeneratingAssembly"));
        }
Example #19
0
 public BamlLocalizableResourceKey FindCorrespondenceKey(BamlLocalizableResourceKey key, BamlLocalizationDictionary dictionary)
 {
     foreach (var entry in dictionary)
     {
         var entryKey = (BamlLocalizableResourceKey)entry.Key;
         if (entryKey.Uid == key.Uid && entryKey.PropertyName == key.PropertyName)
         {
             return(entryKey);
         }
     }
     return(null);
 }
Example #20
0
        //--------------------------------------------------
        // The function follows Managed code parser
        // implementation. in the future, maybe they should
        // share the same code
        //--------------------------------------------------
        private static void GenerateAssembly(LocBamlOptions options, TranslationDictionariesReader dictionaries)
        {
            // there are many names to be used when generating an assembly
            string sourceAssemblyFullName  = options.Input;                                                // source assembly full path
            string outputAssemblyDir       = options.Output;                                               // output assembly directory
            string outputAssemblyLocalName = GetOutputFileName(options);                                   // output assembly name
            string moduleLocalName         = GetAssemblyModuleLocalName(options, outputAssemblyLocalName); // the module name within the assmbly

            // get the source assembly
            byte[]   sourceContents = File.ReadAllBytes(sourceAssemblyFullName);
            Assembly srcAsm         = Assembly.Load(sourceContents);

            // obtain the assembly name
            AssemblyName targetAssemblyNameObj = srcAsm.GetName();

            // store the culture info of the source assembly
            CultureInfo srcCultureInfo = targetAssemblyNameObj.CultureInfo;

            // update it to use it for target assembly
            targetAssemblyNameObj.Name        = Path.GetFileNameWithoutExtension(outputAssemblyLocalName);
            targetAssemblyNameObj.CultureInfo = options.CultureInfo;

            // we get a assembly builder
            AssemblyBuilder targetAssemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(
                targetAssemblyNameObj,                  // name of the assembly
                AssemblyBuilderAccess.RunAndSave,       // access rights
                outputAssemblyDir                       // storage dir
                );

            // we create a module builder for embeded resource modules
            ModuleBuilder moduleBuilder = targetAssemblyBuilder.DefineDynamicModule(
                moduleLocalName,
                outputAssemblyLocalName
                );

            Dictionary <string, IResourceWriter> resourceWriters = new Dictionary <string, IResourceWriter>();

            // If the output assembly already exists, copy the embedded resources to the new assembly
            string existingAssemblyName = Path.Combine(Directory.GetCurrentDirectory(), options.CultureInfo.Name, outputAssemblyLocalName);

            if (File.Exists(existingAssemblyName))
            {
                // Use ReadAllBytes() so we don't hold a file handle open, which would prevent
                // us from overwriting the file at the end.
                Assembly existingAssembly      = Assembly.Load(File.ReadAllBytes(existingAssemblyName));
                string[] existingResourceNames = existingAssembly.GetManifestResourceNames();
                foreach (string resourceName in existingResourceNames)
                {
                    ManifestResourceInfo info = existingAssembly.GetManifestResourceInfo(resourceName);
                    if ((info.ResourceLocation & ResourceLocation.Embedded) != ResourceLocation.Embedded)
                    {
                        continue;
                    }
                    IResourceWriter writer;
                    if (!resourceWriters.TryGetValue(resourceName, out writer))
                    {
                        writer = moduleBuilder.DefineResource(
                            resourceName,             // resource name
                            resourceName,             // resource description
                            ResourceAttributes.Public // visibilty of this resource to other assembly
                            );
                        resourceWriters.Add(resourceName, writer);
                    }
                    Stream resourceStream = existingAssembly.GetManifestResourceStream(resourceName);
                    using (ResourceReader reader = new ResourceReader(resourceStream))
                    {
                        foreach (DictionaryEntry entry in reader)
                        {
                            string key   = entry.Key.ToString();
                            object value = entry.Value;
                            if (key.EndsWith(".baml"))
                            {
                                // Skip it, we're going to get this from the untranslated assembly
                                continue;
                            }
                            writer.AddResource(key, value);
                        }
                    }
                }
            }

            // Add assembly info, trying to preserver original values as close as possible
            CopyAssemblyVersion(targetAssemblyBuilder, srcAsm);

            options.WriteLine(StringLoader.Get("GenerateAssembly"));

            // now for each resource in the assembly
            foreach (string resourceName in srcAsm.GetManifestResourceNames())
            {
                // get the resource location for the resource
                ResourceLocation resourceLocation = srcAsm.GetManifestResourceInfo(resourceName).ResourceLocation;

                // if this resource is in another assemlby, we will skip it
                if ((resourceLocation & ResourceLocation.ContainedInAnotherAssembly) != 0)
                {
                    continue;   // in resource assembly, we don't have resource that is contained in another assembly
                }

                // gets the neutral resource name, giving it the source culture info
                string neutralResourceName = GetNeutralResModuleName(resourceName, srcCultureInfo);

                // gets the target resource name, by giving it the target culture info
                string targetResourceName = GetCultureSpecificResourceName(neutralResourceName, options.CultureInfo);

                // resource stream
                Stream resourceStream = srcAsm.GetManifestResourceStream(resourceName);

                // see if it is a .resources
                if (neutralResourceName.ToLower(CultureInfo.InvariantCulture).EndsWith(".resources"))
                {
                    // now we think we have resource stream
                    // get the resource writer
                    IResourceWriter writer;
                    // check if it is a embeded assembly
                    if (!resourceWriters.TryGetValue(targetResourceName, out writer))
                    {
                        if ((resourceLocation & ResourceLocation.Embedded) != 0)
                        {
                            // gets the resource writer from the module builder
                            writer = moduleBuilder.DefineResource(
                                targetResourceName,         // resource name
                                targetResourceName,         // resource description
                                ResourceAttributes.Public   // visibilty of this resource to other assembly
                                );
                        }
                        else
                        {
                            // it is a standalone resource, we get the resource writer from the assembly builder
                            writer = targetAssemblyBuilder.DefineResource(
                                targetResourceName,         // resource name
                                targetResourceName,         // description
                                targetResourceName,         // file name to save to
                                ResourceAttributes.Public   // visibility of this resource to other assembly
                                );
                        }
                        resourceWriters.Add(targetResourceName, writer);
                    }

                    // get the resource reader
                    IResourceReader reader = new ResourceReader(resourceStream);

                    // generate the resources
                    GenerateResourceStream(options, resourceName, reader, writer, dictionaries);

                    // we don't call writer.Generate() or writer.Close() here
                    // because the AssemblyBuilder will call them when we call Save() on it.
                }
                else
                {
                    // else it is a stand alone untyped manifest resources.
                    string extension = Path.GetExtension(targetResourceName);

                    string fullFileName = Path.Combine(outputAssemblyDir, targetResourceName);

                    // check if it is a .baml, case-insensitive
                    if (string.Compare(extension, ".baml", true, CultureInfo.InvariantCulture) == 0)
                    {
                        // try to localized the the baml
                        // find the resource dictionary
                        BamlLocalizationDictionary dictionary = dictionaries[resourceName];

                        // if it is null, just create an empty dictionary.
                        if (dictionary != null)
                        {
                            // it is a baml stream
                            using (Stream output = File.OpenWrite(fullFileName))
                            {
                                options.Write("    ");
                                options.WriteLine(StringLoader.Get("GenerateStandaloneBaml", fullFileName));
                                GenerateBamlStream(resourceStream, output, dictionary, options);
                                options.WriteLine(StringLoader.Get("Done"));
                            }
                        }
                        else
                        {
                            // can't find localization of it, just copy it
                            GenerateStandaloneResource(fullFileName, resourceStream);
                        }
                    }
                    else
                    {
                        // it is an untyped resource stream, just copy it
                        GenerateStandaloneResource(fullFileName, resourceStream);
                    }

                    // now add this resource file into the assembly
                    targetAssemblyBuilder.AddResourceFile(
                        targetResourceName,           // resource name
                        targetResourceName,           // file name
                        ResourceAttributes.Public     // visibility of the resource to other assembly
                        );
                }
            }

            // at the end, generate the assembly
            targetAssemblyBuilder.Save(outputAssemblyLocalName);
            options.WriteLine(StringLoader.Get("DoneGeneratingAssembly"));
        }
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="reader">resoure text reader that reads CSV or a tab-separated txt file</param>
        internal TranslationDictionariesReader(ResourceTextReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            // hash key is case insensitive strings
            _table = new Hashtable();

            // we read each Row
            int rowNumber = 0;

            while (reader.ReadRow())
            {
                rowNumber++;

                // field #1 is the baml name.
                string bamlName = reader.GetColumn(0);

                // it can't be null
                if (bamlName == null)
                {
                    throw new ApplicationException(StringLoader.Get("EmptyRowEncountered"));
                }

                if (string.IsNullOrEmpty(bamlName))
                {
                    // allow for comment lines in csv file.
                    // each comment line starts with ",". It will make the first entry as String.Empty.
                    // and we will skip the whole line.
                    continue;   // if the first column is empty, take it as a comment line
                }

                // field #2: key to the localizable resource
                string key = reader.GetColumn(1);
                if (key == null)
                {
                    throw new ApplicationException(StringLoader.Get("NullBamlKeyNameInRow"));
                }

                BamlLocalizableResourceKey resourceKey = LocBamlConst.StringToResourceKey(key);

                // get the dictionary
                BamlLocalizationDictionary dictionary = this[bamlName];
                if (dictionary == null)
                {
                    // we create one if it is not there yet.
                    dictionary     = new BamlLocalizationDictionary();
                    this[bamlName] = dictionary;
                }

                BamlLocalizableResource resource;

                // the rest of the fields are either all null,
                // or all non-null. If all null, it means the resource entry is deleted.

                // get the string category
                string categoryString = reader.GetColumn(2);
                if (categoryString == null)
                {
                    // it means all the following fields are null starting from column #3.
                    resource = null;
                }
                else
                {
                    // the rest must all be non-null.
                    // the last cell can be null if there is no content
                    for (int i = 3; i < 6; i++)
                    {
                        if (reader.GetColumn(i) == null)
                        {
                            throw new Exception(StringLoader.Get("InvalidRow"));
                        }
                    }

                    // now we know all are non-null. let's try to create a resource
                    resource = new BamlLocalizableResource();

                    // field #3: Category
                    resource.Category = (LocalizationCategory)StringCatConverter.ConvertFrom(categoryString);

                    // field #4: Readable
                    resource.Readable = (bool)BoolTypeConverter.ConvertFrom(reader.GetColumn(3));

                    // field #5: Modifiable
                    resource.Modifiable = (bool)BoolTypeConverter.ConvertFrom(reader.GetColumn(4));

                    // field #6: Comments
                    resource.Comments = reader.GetColumn(5);

                    // field #7: Content
                    resource.Content = reader.GetColumn(6);

                    // in case content being the last column, consider null as empty.
                    if (resource.Content == null)
                    {
                        resource.Content = string.Empty;
                    }

                    // field > #7: Ignored.
                }

                // at this point, we are good.
                // add to the dictionary.
                dictionary.Add(resourceKey, resource);
            }
        }
        private static void CreateMissingBamlTreeNode(
            BamlLocalizationDictionary dictionary,
            BamlTreeUpdateMap treeMap
            )
        {
            BamlLocalizationDictionaryEnumerator enumerator = dictionary.GetEnumerator();

            while (enumerator.MoveNext())
            {
                BamlLocalizableResourceKey key      = enumerator.Key;
                BamlLocalizableResource    resource = enumerator.Value;

                // get the baml tree node from the tree
                BamlTreeNode node = treeMap.MapKeyToBamlTreeNode(key);

                if (node == null)
                {
                    if (key.PropertyName == BamlConst.ContentSuffix)
                    {
                        // see if there is already a Baml node with the Uid. If so
                        // ignore this entry
                        node = treeMap.MapUidToBamlTreeElementNode(key.Uid);
                        if (node == null)
                        {
                            // create new Baml element node
                            BamlStartElementNode newNode = new BamlStartElementNode(
                                treeMap.Resolver.ResolveAssemblyFromClass(key.ClassName),
                                key.ClassName,
                                false, /*isInjected*/
                                false  /*CreateUsingTypeConverter*/
                                );

                            // create new x:Uid node for this element node
                            newNode.AddChild(
                                new BamlDefAttributeNode(
                                    XamlReaderHelper.DefinitionUid,
                                    key.Uid
                                    )
                                );

                            TryAddContentPropertyToNewElement(treeMap, newNode);

                            // terminate the node with EndElementNode
                            newNode.AddChild(new BamlEndElementNode());

                            // store this new node into the map so that it can be found
                            // when other translations reference it as a childplace holder, or property owner
                            treeMap.AddBamlTreeNode(key.Uid, key, newNode);
                        }
                    }
                    else
                    {
                        BamlTreeNode newNode;
                        if (key.PropertyName == BamlConst.LiteralContentSuffix)
                        {
                            // create a LiterContent node
                            newNode = new BamlLiteralContentNode(resource.Content);
                        }
                        else
                        {
                            newNode = new BamlPropertyNode(
                                treeMap.Resolver.ResolveAssemblyFromClass(key.ClassName),
                                key.ClassName,
                                key.PropertyName,
                                resource.Content,
                                BamlAttributeUsage.Default
                                );
                        }

                        // add to the map
                        treeMap.AddBamlTreeNode(null, key, newNode);
                    }
                }
            }
        }
        /// <summary>
        /// Write the localizable key-value pairs
        /// </summary>
        /// <param name="options"></param>
        internal static void Write(LocBamlOptions options)
        {
            Stream output = new FileStream(options.Output, FileMode.Create);
            InputBamlStreamList bamlStreamList = new InputBamlStreamList(options);

            using (ResourceTextWriter writer = new ResourceTextWriter(options.TranslationFileType, output))
            {
                options.WriteLine(StringLoader.Get("WriteBamlValues"));
                for (int i = 0; i < bamlStreamList.Count; i++)
                {
                    options.Write("    ");
                    options.Write(StringLoader.Get("ProcessingBaml", bamlStreamList[i].Name));

                    // Search for comment file in the same directory. The comment file has the extension to be
                    // "loc".
                    string     commentFile   = Path.ChangeExtension(bamlStreamList[i].Name, "loc");
                    TextReader commentStream = null;

                    try
                    {
                        if (File.Exists(commentFile))
                        {
                            commentStream = new StreamReader(commentFile);
                        }

                        // create the baml localizer
                        BamlLocalizer mgr = new BamlLocalizer(
                            bamlStreamList[i].Stream,
                            new BamlLocalizabilityByReflection(options.Assemblies),
                            commentStream
                            );

                        // extract localizable resource from the baml stream
                        BamlLocalizationDictionary dict = mgr.ExtractResources();

                        // write out each resource
                        foreach (DictionaryEntry entry in dict)
                        {
                            // column 1: baml stream name
                            writer.WriteColumn(bamlStreamList[i].Name);

                            BamlLocalizableResourceKey key      = (BamlLocalizableResourceKey)entry.Key;
                            BamlLocalizableResource    resource = (BamlLocalizableResource)entry.Value;

                            // column 2: localizable resource key
                            writer.WriteColumn(LocBamlConst.ResourceKeyToString(key));

                            // column 3: localizable resource's category
                            writer.WriteColumn(resource.Category.ToString());

                            // column 4: localizable resource's readability
                            writer.WriteColumn(resource.Readable.ToString());

                            // column 5: localizable resource's modifiability
                            writer.WriteColumn(resource.Modifiable.ToString());

                            // column 6: localizable resource's localization comments
                            writer.WriteColumn(resource.Comments);

                            // column 7: localizable resource's content
                            writer.WriteColumn(resource.Content);

                            // Done. finishing the line
                            writer.EndLine();
                        }

                        options.WriteLine(StringLoader.Get("Done"));
                    }
                    finally
                    {
                        if (commentStream != null)
                        {
                            commentStream.Close();
                        }
                    }
                }

                // close all the baml input streams, output stream is closed by writer.
                bamlStreamList.Close();
            }
        }
        /// <summary>
        /// Generates localized Baml from translations
        /// </summary>
        /// <param name="options">LocBaml options</param>
        /// <param name="dictionaries">the translation dictionaries</param>
        internal static string Generate(LocBamlOptions options, TranslationDictionariesReader dictionaries)
        {
            // base on the input, we generate differently
            switch (options.InputType)
            {
            case FileType.BAML:
            {
                // input file name
                string bamlName = Path.GetFileName(options.Input);

                // output file name is output dir + input file name
                string outputFileName = GetOutputFileName(options);

                // construct the full path
                string fullPathOutput = Path.Combine(options.Output, outputFileName);

                options.Write(StringLoader.Get("GenerateBaml", fullPathOutput));

                using (Stream input = File.OpenRead(options.Input))
                {
                    using (Stream output = new FileStream(fullPathOutput, FileMode.Create))
                    {
                        BamlLocalizationDictionary dictionary = dictionaries[bamlName];

                        // if it is null, just create an empty dictionary.
                        if (dictionary == null)
                        {
                            dictionary = new BamlLocalizationDictionary();
                        }

                        string status = GenerateBamlStream(input, output, dictionary, options);
                        if (status != null)
                        {
                            return(status);
                        }
                    }
                }

                options.WriteLine(StringLoader.Get("Done"));
                break;
            }

            case FileType.RESOURCES:
            {
                string outputFileName = GetOutputFileName(options);
                string fullPathOutput = Path.Combine(options.Output, outputFileName);

                using (Stream input = File.OpenRead(options.Input))
                {
                    using (Stream output = File.OpenWrite(fullPathOutput))
                    {
                        // create a Resource reader on the input;
                        IResourceReader reader = new ResourceReader(input);

                        // create a writer on the output;
                        IResourceWriter writer = new ResourceWriter(output);

                        string status = GenerateResourceStream(
                            options,             // options
                            options.Input,       // resources name
                            reader,              // resource reader
                            writer,              // resource writer
                            dictionaries);       // translations

                        reader.Close();
                        if (status != null)
                        {
                            return(status);
                        }
                        // now generate and close
                        writer.Generate();
                        writer.Close();
                    }
                }

                options.WriteLine(StringLoader.Get("DoneGeneratingResource", outputFileName));
                break;
            }

            case FileType.EXE:
            case FileType.DLL:
            {
                string status = GenerateAssembly(options, dictionaries);
                if (status != null)
                {
                    return(status);
                }
                break;
            }

            default:
            {
                Debug.Assert(false, "Can't generate to this type");
                return("Can't generate to a resource of the type EXE");

                break;
            }
            }

            return(null);
        }