/// <summary> /// Generates localized Baml from translations /// </summary> /// <param name="options">LocBaml options</param> /// <param name="dictionaries">the translation dictionaries</param> internal static void Generate(LocBamlOptions options, TranslationDictionariesReader dictionaries) { // base on the input, we generate differently switch (options.InputType) { case FileType.BAML: { throw new Exception("Is not supported yet"); break; } case FileType.RESOURCES: { throw new Exception("Is not supported yet"); break; } case FileType.EXE: case FileType.DLL: { GenerateAssembly(options, dictionaries); break; } default: { Debug.Assert(false, "Can't generate to this type"); break; } } }
/// <summary> /// Genereate localized baml /// </summary> private static void GenerateBamlResources(LocBamlOptions options) { Stream input = File.OpenRead(options.TranslationsFile); using (ResourceTextReader reader = new ResourceTextReader(options.TranslationFileType, input)) { TranslationDictionariesReader dictionaries = new TranslationDictionariesReader(reader); ResourceGenerator.Generate(options, dictionaries); } }
//-------------------------------------------------- // 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 throw new Exception("This vertion doesn't support this function"); }
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); } } }