Esempio n. 1
0
 private static void PrintLogo(LocBamlOptions option)
 {
     if (option == null || !option.HasNoLogo)
     {
         Console.WriteLine(StringLoader.Get("Msg_Copyright", GetAssemblyVersion()));
     }
 }
Esempio n. 2
0
        internal static BamlLocalizableResourceKey StringToResourceKey(string value)
        {
            int nameEnd = value.LastIndexOf(':');

            if (nameEnd < 0)
            {
                throw new ArgumentException(StringLoader.Get("ResourceKeyFormatError"));
            }

            string name     = value.Substring(0, nameEnd);
            int    classEnd = value.LastIndexOf('.');

            if (classEnd < 0 || classEnd < nameEnd || classEnd == value.Length)
            {
                throw new ArgumentException(StringLoader.Get("ResourceKeyFormatError"));
            }

            string className    = value.Substring(nameEnd + 1, classEnd - nameEnd - 1);
            string propertyName = value.Substring(classEnd + 1);

            return(new BamlLocalizableResourceKey(
                       name,
                       className,
                       propertyName
                       ));
        }
Esempio n. 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();
            }
        }
Esempio n. 4
0
        public static int Main(string[] args)
        {
            //Debugger.Break();
            AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;

            LocBamlOptions options;
            string         errorMessage;

            GetCommandLineOptions(args, out options, out errorMessage);

            if (errorMessage != null)
            {
                // there are errors
                PrintLogo(options);
                Console.WriteLine(StringLoader.Get("ErrorMessage", errorMessage));
                Console.WriteLine();
                PrintUsage();
                return(ErrorCode);    // error
            }

            // at this point, we obtain good options.
            if (options == null)
            {
                // no option to process. Noop.
                return(SuccessCode);
            }

            _dispatcher = Dispatcher.CurrentDispatcher;

            PrintLogo(options);

            try{
                // it is to parse
                if (options.ToParse)
                {
                    ParseBamlResources(options);
                }
                else
                {
                    GenerateBamlResources(options);
                }
            }
            catch (Exception e)
            {
#if DEBUG
                throw e;
#else
                Console.WriteLine(e.Message);
                return(ErrorCode);
#endif
            }

            return(SuccessCode);
        }
Esempio n. 5
0
        public static int Main(string[] args)
        {
            //register "pack://" uri
            System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(Application).TypeHandle);

            LocBamlOptions options;
            string         errorMessage;

            GetCommandLineOptions(args, out options, out errorMessage);

            if (errorMessage != null)
            {
                // there are errors
                PrintLogo(options);
                Console.WriteLine(StringLoader.Get("ErrorMessage", errorMessage));
                Console.WriteLine();
                PrintUsage();
                return(ErrorCode);    // error
            }

            // at this point, we obtain good options.
            if (options == null)
            {
                // no option to process. Noop.
                return(SuccessCode);
            }

            _dispatcher = Dispatcher.CurrentDispatcher;

            PrintLogo(options);

            try{
                // it is to parse
                if (options.ToParse)
                {
                    ParseBamlResources(options);
                }
                else
                {
                    GenerateBamlResources(options);
                }
            }
            catch (Exception e)
            {
#if DEBUG
                throw e;
#else
                Console.WriteLine(e.Message);
                return(ErrorCode);
#endif
            }

            return(SuccessCode);
        }
Esempio n. 6
0
        public String Lookup(String strOpt, out bool bRequiresValue, out bool bCanHaveValue)
        {
            String strOptLower = strOpt.ToLower(CultureInfo.InvariantCulture);
            int    i;
            bool   bMatched = false;
            int    iMatch   = -1;

            // Compare option to stored list.
            for (i = 0; i < m_aOptions.Length; i++)
            {
                // Exact matches always cause immediate termination of
                // the search
                if (strOptLower.Equals(m_aOptions[i]))
                {
                    bRequiresValue = m_bRequiresValue[i];
                    bCanHaveValue  = m_bCanHaveValue[i];
                    return(m_aOptions[i]);
                }

                // Check for potential match (the input word is a prefix
                // of the current stored option).
                if (m_aOptions[i].StartsWith(strOptLower))
                {
                    // If we've already seen a prefix match then the
                    // input word is ambiguous.
                    if (bMatched)
                    {
                        throw new ArgumentException(StringLoader.Get("Err_AmbigousOption", strOpt));
                    }

                    // Remember this partial match.
                    bMatched = true;
                    iMatch   = i;
                }
            }

            // If we get here with bMatched set, we saw one and only one
            // partial match, so we've got a winner.
            if (bMatched)
            {
                bRequiresValue = m_bRequiresValue[iMatch];
                bCanHaveValue  = m_bCanHaveValue[iMatch];
                return(m_aOptions[iMatch]);
            }

            // Else the word doesn't match at all.
            throw new ArgumentException(StringLoader.Get("Err_UnknownOption", strOpt));
        }
Esempio n. 7
0
        public CommandLine(String[] aArgs, String[] aValidOpts)
        {
            int i, iArg, iOpt;

            // Keep a list of valid option names.
            m_sValidOptions = new Abbrevs(aValidOpts);

            // Temporary lists of raw arguments and options and their
            // associated values.
            String[] aArgList = new String[aArgs.Length];
            Option[] aOptList = new Option[aArgs.Length];

            // Reset counters of raw arguments and option/value pairs found
            // so far.
            iArg = 0;
            iOpt = 0;

            // Iterate through words of command line.
            for (i = 0; i < aArgs.Length; i++)
            {
                // Check for option or raw argument.
                if (aArgs[i].StartsWith("/") ||
                    aArgs[i].StartsWith("-"))
                {
                    String strOpt;
                    String strVal = null;
                    bool   bRequiresValue;
                    bool   bCanHaveValue;

                    // It's an option. Strip leading '/' or '-' and
                    // anything after a value separator (':' or
                    // '=').
                    int iColon = aArgs[i].IndexOfAny(new char[] { ':', '=' });
                    if (iColon == -1)
                    {
                        strOpt = aArgs[i].Substring(1);
                    }
                    else
                    {
                        strOpt = aArgs[i].Substring(1, iColon - 1);
                    }

                    // Look it up in the table of valid options (to
                    // check it exists, get the full option name and
                    // to see if an associated value is expected).
                    strOpt = m_sValidOptions.Lookup(strOpt, out bRequiresValue, out bCanHaveValue);

                    // Check that the user hasn't specified a value separator for an option
                    // that doesn't take a value.
                    if (!bCanHaveValue && (iColon != -1))
                    {
                        throw new ApplicationException(StringLoader.Get("Err_NoValueRequired", strOpt));
                    }

                    // Check that the user has put a colon if the option requires a value.
                    if (bRequiresValue && (iColon == -1))
                    {
                        throw new ApplicationException(StringLoader.Get("Err_ValueRequired", strOpt));
                    }

                    // Go look for a value if there is one.
                    if (bCanHaveValue && iColon != -1)
                    {
                        if (iColon == (aArgs[i].Length - 1))
                        {
                            // No value separator, or
                            // separator is at end of
                            // option; look for value in
                            // next command line arg.
                            if (i + 1 == aArgs.Length)
                            {
                                throw new ApplicationException(StringLoader.Get("Err_ValueRequired", strOpt));
                            }
                            else
                            {
                                if ((aArgs[i + 1].StartsWith("/") || aArgs[i + 1].StartsWith("-")))
                                {
                                    throw new ApplicationException(StringLoader.Get("Err_ValueRequired", strOpt));
                                }

                                strVal = aArgs[i + 1];
                                i++;
                            }
                        }
                        else
                        {
                            // Value is in same command line
                            // arg as the option, substring
                            // it out.
                            strVal = aArgs[i].Substring(iColon + 1);
                        }
                    }

                    // Build the option value pair.
                    aOptList[iOpt++] = new Option(strOpt, strVal);
                }
                else
                {
                    // Command line word is a raw argument.
                    aArgList[iArg++] = aArgs[i];
                }
            }

            // Allocate the non-temporary arg and option lists at exactly
            // the right size.
            m_aArgList = new String[iArg];
            m_aOptList = new Option[iOpt];

            // Copy in the values we've calculated.
            Array.Copy(aArgList, m_aArgList, iArg);
            Array.Copy(aOptList, m_aOptList, iOpt);
        }
        /// <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);
        }
        //--------------------------------------------------
        // The function follows Managed code parser
        // implementation. in the future, maybe they should
        // share the same code
        //--------------------------------------------------
        private static string 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 assembly

            // 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
                );

            // we create a module builder for embedded 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 assembly, 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 embedded 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   // visibility 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
                    string status = GenerateResourceStream(options, resourceName, reader, writer, dictionaries);
                    if (status != null)
                    {
                        return(status);
                    }

                    // 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 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"));
            return(null);
        }
        private static string GenerateResourceStream(
            LocBamlOptions 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
                        string status = GenerateBamlStream(
                            (Stream)entry.Value,
                            targetStream,
                            localizations,
                            options
                            );
                        if (status != null)
                        {
                            options.WriteLine(status);
                            return(status);
                        }
                    }

                    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);
                }
            }

            return(null);
        }
Esempio n. 11
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"));
        }
Esempio n. 12
0
        /// <summary>
        /// return true if the operation succeeded.
        /// otherwise, return false
        /// </summary>
        internal string  CheckAndSetDefault()
        {
            // we validate the options here and also set default
            // if we can

            // Rule #1: One and only one action at a time
            // i.e. Can't parse and generate at the same time
            //      Must do one of them
            if ((ToParse && ToGenerate) ||
                (!ToParse && !ToGenerate))
            {
                return(StringLoader.Get("MustChooseOneAction"));
            }

            // Rule #2: Must have an input
            if (string.IsNullOrEmpty(Input))
            {
                return(StringLoader.Get("InputFileRequired"));
            }
            else
            {
                if (!File.Exists(Input))
                {
                    return(StringLoader.Get("FileNotFound", Input));
                }

                string extension = Path.GetExtension(Input);

                // Get the input file type.
                if (string.Compare(extension, "." + FileType.BAML.ToString(), true, CultureInfo.InvariantCulture) == 0)
                {
                    InputType = FileType.BAML;
                }
                else if (string.Compare(extension, "." + FileType.RESOURCES.ToString(), true, CultureInfo.InvariantCulture) == 0)
                {
                    InputType = FileType.RESOURCES;
                }
                else if (string.Compare(extension, "." + FileType.DLL.ToString(), true, CultureInfo.InvariantCulture) == 0)
                {
                    InputType = FileType.DLL;
                }
                else if (string.Compare(extension, "." + FileType.EXE.ToString(), true, CultureInfo.InvariantCulture) == 0)
                {
                    InputType = FileType.EXE;
                }
                else
                {
                    return(StringLoader.Get("FileTypeNotSupported", extension));
                }
            }

            if (ToGenerate)
            {
                // Rule #3: before generation, we must have Culture string
                if (CultureInfo == null && InputType != FileType.BAML)
                {
                    // if we are not generating baml,
                    return(StringLoader.Get("CultureNameNeeded", InputType.ToString()));
                }

                // Rule #4: before generation, we must have translation file
                if (string.IsNullOrEmpty(Translations))
                {
                    return(StringLoader.Get("TranslationNeeded"));
                }
                else
                {
                    string extension = Path.GetExtension(Translations);

                    if (!File.Exists(Translations))
                    {
                        return(StringLoader.Get("TranslationNotFound", Translations));
                    }
                    else
                    {
                        if (string.Compare(extension, "." + FileType.CSV.ToString(), true, CultureInfo.InvariantCulture) == 0)
                        {
                            TranslationFileType = FileType.CSV;
                        }
                        else
                        {
                            TranslationFileType = FileType.TXT;
                        }
                    }
                }
            }



            // Rule #5: If the output file name is empty, we act accordingly
            if (string.IsNullOrEmpty(Output))
            {
                // Rule #5.1: If it is parse, we default to [input file name].csv
                if (ToParse)
                {
                    string fileName = Path.GetFileNameWithoutExtension(Input);
                    Output = fileName + "." + FileType.CSV.ToString();
                    TranslationFileType = FileType.CSV;
                }
                else
                {
                    // Rule #5.2: If it is generating, and the output can't be empty
                    return(StringLoader.Get("OutputDirectoryNeeded"));
                }
            }
            else
            {
                // output isn't null, we will determind the Output file type
                // Rule #6: if it is parsing. It will be .csv or .txt.
                if (ToParse)
                {
                    string fileName;
                    string outputDir;

                    if (Directory.Exists(Output))
                    {
                        // the output is actually a directory name
                        fileName  = string.Empty;
                        outputDir = Output;
                    }
                    else
                    {
                        // get the extension
                        fileName  = Path.GetFileName(Output);
                        outputDir = Path.GetDirectoryName(Output);
                    }

                    // Rule #6.1: if it is just the output directory
                    // we append the input file name as the output + csv as default
                    if (string.IsNullOrEmpty(fileName))
                    {
                        TranslationFileType = FileType.CSV;
                        Output = outputDir
                                 + Path.DirectorySeparatorChar
                                 + Path.GetFileName(Input)
                                 + "."
                                 + TranslationFileType.ToString();
                    }
                    else
                    {
                        // Rule #6.2: if we have file name, check the extension.
                        string extension = Path.GetExtension(Output);

                        // ignore case and invariant culture
                        if (string.Compare(extension, "." + FileType.CSV.ToString(), true, CultureInfo.InvariantCulture) == 0)
                        {
                            TranslationFileType = FileType.CSV;
                        }
                        else
                        {
                            // just consider the output as txt format if it doesn't have .csv extension
                            TranslationFileType = FileType.TXT;
                        }
                    }
                }
                else
                {
                    // it is to generate. And Output should point to the directory name.
                    if (!Directory.Exists(Output))
                    {
                        return(StringLoader.Get("OutputDirectoryError", Output));
                    }
                }
            }

            // Rule #7: if the input assembly path is not null
            if (AssemblyPaths != null && AssemblyPaths.Count > 0)
            {
                Assemblies = new Assembly[AssemblyPaths.Count];
                for (int i = 0; i < Assemblies.Length; i++)
                {
                    string errorMsg = null;
                    try
                    {
                        // load the assembly
                        Assemblies[i] = Assembly.LoadFrom((string)AssemblyPaths[i]);
                    }
                    catch (ArgumentException argumentError)
                    {
                        errorMsg = argumentError.Message;
                    }
                    catch (BadImageFormatException formatError)
                    {
                        errorMsg = formatError.Message;
                    }
                    catch (FileNotFoundException fileError)
                    {
                        errorMsg = fileError.Message;
                    }
                    catch (PathTooLongException pathError)
                    {
                        errorMsg = pathError.Message;
                    }
                    catch (SecurityException securityError)
                    {
                        errorMsg = securityError.Message;
                    }

                    if (errorMsg != null)
                    {
                        return(errorMsg); // return error message when loading this assembly
                    }
                }
            }

            // if we come to this point, we are all fine, return null error message
            return(null);
        }
Esempio n. 13
0
 private static void PrintUsage()
 {
     Console.WriteLine(StringLoader.Get("Msg_Usage"));
 }
Esempio n. 14
0
        /// <summary>
        /// get CommandLineOptions, return error message
        /// </summary>
        private static void GetCommandLineOptions(string[] args, out LocBamlOptions options, out string errorMessage)
        {
            CommandLine commandLine;

            try{
                // "*" means the option must have a value. no "*" means the option can't have a value
                commandLine = new CommandLine(args,
                                              new string[] {
                    "parse",                                // /parse for update
                    "generate",                             // /generate     for generate
                    "*out",                                 // /out          for output .csv|.txt when parsing, for output directory when generating
                    "*culture",                             // /culture      for culture name
                    "*translation",                         // /translation  for translation file, .csv|.txt
                    "*asmpath",                             // /asmpath,     for assembly path to look for references   (TODO: add asmpath support)
                    "nologo",                               // /nologo       for not to print logo
                    "help",                                 // /help         for help
                    "verbose"                               // /verbose      for verbose output
                }
                                              );
            }
            catch (ArgumentException e)
            {
                errorMessage = e.Message;
                options      = null;
                return;
            }

            if (commandLine.NumArgs + commandLine.NumOpts < 1)
            {
                PrintLogo(null);
                PrintUsage();
                errorMessage = null;
                options      = null;
                return;
            }

            options = new LocBamlOptions();

            options.Input = commandLine.GetNextArg();

            Option commandLineOption;

            while ((commandLineOption = commandLine.GetNextOption()) != null)
            {
                if (commandLineOption.Name == "parse")
                {
                    options.ToParse = true;
                }
                else if (commandLineOption.Name == "generate")
                {
                    options.ToGenerate = true;
                }
                else if (commandLineOption.Name == "nologo")
                {
                    options.HasNoLogo = true;
                }
                else if (commandLineOption.Name == "help")
                {
                    // we print usage and stop processing
                    PrintUsage();
                    errorMessage = null;
                    options      = null;
                    return;
                }
                else if (commandLineOption.Name == "verbose")
                {
                    options.IsVerbose = true;
                }
                // the following ones need value
                else if (commandLineOption.Name == "out")
                {
                    options.Output = commandLineOption.Value;
                }
                else if (commandLineOption.Name == "translation")
                {
                    options.Translations = commandLineOption.Value;
                }
                else if (commandLineOption.Name == "asmpath")
                {
                    if (options.AssemblyPaths == null)
                    {
                        options.AssemblyPaths = new ArrayList();
                    }

                    options.AssemblyPaths.Add(commandLineOption.Value);
                }
                else if (commandLineOption.Name == "culture")
                {
                    try
                    {
                        options.CultureInfo = new CultureInfo(commandLineOption.Value);
                    }
                    catch (ArgumentException e)
                    {
                        // Error
                        errorMessage = e.Message;
                        return;
                    }
                }
                else
                {
                    // something that we don't recognize
                    errorMessage = StringLoader.Get("Err_InvalidOption", commandLineOption.Name);
                    return;
                }
            }

            // we passed all the test till here. Now check the combinations of the options
            errorMessage = options.CheckAndSetDefault();
        }
        /// <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);
            }
        }
        /// <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();
            }
        }
Esempio n. 17
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"));
        }