Exemplo n.º 1
0
        /// <summary>
        /// This method parses the Watcher Value Translation table from the plugin configuration.
        /// </summary>
        /// <param name="root">The root node of the configuration.</param>
        private void ParseValueTranslationTable(XElement root)
        {
            // Search for a value translation node
            XElement valueTranslationElement = root.Element("ValueTranslation", StringComparison.OrdinalIgnoreCase);

            if (valueTranslationElement == null)
            {
                Trace.TraceInformation("Value translation table does not appear to exist.");
                return;
            }

            Trace.TraceInformation("Found the value translation table.");

            // Extract the fields whose values will be translated
            IEnumerable <XElement> watcherFields = valueTranslationElement.Elements("WatcherField", StringComparison.OrdinalIgnoreCase);

            foreach (XElement watcherField in watcherFields)
            {
                // Create a new translation instance, and store the name of the field to translate
                TranslationEntry entry = new TranslationEntry();
                entry.Field = watcherField.AttributeValue("Name", StringComparison.OrdinalIgnoreCase);

                // Extract the possible values of each field, and what value they should be translated to
                IEnumerable <XElement> watcherFieldValues = watcherField.Elements("Value", StringComparison.OrdinalIgnoreCase);
                foreach (XElement watcherFieldValue in watcherFieldValues)
                {
                    entry.TranslationTable.Add(
                        watcherFieldValue.AttributeValue("From", StringComparison.OrdinalIgnoreCase),
                        watcherFieldValue.AttributeValue("To", StringComparison.OrdinalIgnoreCase)
                        );
                }

                // Add the translation instance to the translation table
                this.Translation.Add(entry.Field, entry);
            }
        }
        /// <inheritdoc/>
        public void Execute(GeneratorExecutionContext context)
        {
            try
            {
                // get generator options
                string @namespace     = this.ReadOption(context, "Namespace", raw => raw) ?? this.GetRootNamespace(context) ?? "Pathoschild.I18n";
                string className      = this.ReadOption(context, "ClassName", raw => raw) ?? "I18n";
                string classModifiers = this.ReadOption(context, "ClassModifiers", raw => raw) ?? "internal static";
                bool   addGetByKey    = this.ReadOption <bool?>(context, "AddGetByKey", raw => bool.Parse(raw)) ?? false;
                bool   addKeyMap      = this.ReadOption <bool?>(context, "AddKeyMap", raw => bool.Parse(raw)) ?? false;

                // get translations
                TranslationEntry[] entries = this.ReadTranslationFile(context, new HashSet <string>(this.GetReservedNames(className, addKeyMap)));

                // build output
                StringBuilder output = new();
                output
                .AppendLine("#nullable enable")
                .AppendLine("using System;")
                .AppendLine("using System.CodeDom.Compiler;");

                if (entries.Any(p => p.TokenParameterStyle == TokenParameterStyle.Dictionary))
                {
                    output
                    .AppendLine("using System.Collections.Generic;");
                }

                output
                .AppendLine("using System.Diagnostics.CodeAnalysis;")
                .AppendLine("using StardewModdingAPI;")
                .AppendLine()
                .AppendLine($"namespace {@namespace}")
                .AppendLine("{")
                .AppendLine("    /// <summary>Get translations from the mod's <c>i18n</c> folder.</summary>")
                .AppendLine("    /// <remarks>This is auto-generated from the <c>i18n/default.json</c> file when the project is compiled.</remarks>")
                .AppendLine(@"    [GeneratedCode(""TextTemplatingFileGenerator"", ""1.0.0"")]")
                .AppendLine(@"    [SuppressMessage(""ReSharper"", ""InconsistentNaming"", Justification = ""Deliberately named for consistency and to match translation conventions."")]")
                .AppendLine($"    {classModifiers} class {className}")
                .AppendLine("    {")
                .AppendLine("        /*********")
                .AppendLine("        ** Fields")
                .AppendLine("        *********/")
                .AppendLine("        /// <summary>The mod's translation helper.</summary>")
                .AppendLine("        private static ITranslationHelper? Translations;")
                .AppendLine()
                .AppendLine();

                if (addKeyMap)
                {
                    output
                    .AppendLine("        /*********")
                    .AppendLine("        ** Accessors")
                    .AppendLine("        *********/")
                    .AppendLine("        /// <summary>A lookup of available translation keys.</summary>")
                    .AppendLine(@"        [SuppressMessage(""ReSharper"", ""MemberHidesStaticFromOuterClass"", Justification = ""Using the same key is deliberate."")]")
                    .AppendLine("        public static class Keys")
                    .AppendLine("        {");

                    for (int i = 0; i < entries.Length; i++)
                    {
                        TranslationEntry entry = entries[i];

                        if (i != 0)
                        {
                            output.AppendLine();
                        }

                        output
                        .AppendLine($@"            /// <summary>The unique key for a translation equivalent to ""{entry.GetTranslationTextForXmlDoc()}"".</summary>")
                        .AppendLine($@"            public const string {entry.MethodName} = ""{entry.Key}"";");
                    }

                    output
                    .AppendLine("        }")
                    .AppendLine()
                    .AppendLine();
                }

                output
                .AppendLine("        /*********")
                .AppendLine("        ** Public methods")
                .AppendLine("        *********/")
                .AppendLine("        /// <summary>Construct an instance.</summary>")
                .AppendLine(@"        /// <param name=""translations"">The mod's translation helper.</param>")
                .AppendLine("        public static void Init(ITranslationHelper translations)")
                .AppendLine("        {")
                .AppendLine($"            {className}.Translations = translations;")
                .AppendLine("        }");

                foreach (TranslationEntry entry in entries)
                {
                    // summary doc
                    output
                    .AppendLine()
                    .AppendLine($@"        /// <summary>Get a translation equivalent to ""{entry.GetTranslationTextForXmlDoc()}"".</summary>");

                    // param docs
                    foreach (var token in entry.Tokens)
                    {
                        output.AppendLine($@"        /// <param name=""{this.PrefixIdentifierIfNeeded(token.ParameterName)}"">The value to inject for the <c>{{{{{token.Key}}}}}</c> token.</param>");
                    }

                    // method
                    {
                        string renderedKey      = addKeyMap ? $"Keys.{entry.MethodName}" : $@"""{entry.Key}""";
                        string renderedArgs     = string.Join(", ", entry.Tokens.Select(token => $"object {token.ParameterName}"));
                        string renderedTokenObj = entry.Tokens.Any() ? $", {this.GenerateTokenParameter(entry)}" : "";

                        output
                        .AppendLine($@"        public static string {entry.MethodName}({renderedArgs})")
                        .AppendLine("        {")
                        .AppendLine($@"            return {className}.GetByKey({renderedKey}{renderedTokenObj});")
                        .AppendLine("        }");
                    }
                }

                if (addGetByKey)
                {
                    output.AppendLine();
                }
                else
                {
                    output
                    .AppendLine()
                    .AppendLine()
                    .AppendLine("        /*********")
                    .AppendLine("        ** Private methods")
                    .AppendLine("        *********/");
                }

                output
                .AppendLine("        /// <summary>Get a translation by its key.</summary>")
                .AppendLine(@"        /// <param name=""key"">The translation key.</param>")
                .AppendLine(@"        /// <param name=""tokens"">An object containing token key/value pairs. This can be an anonymous object (like <c>new { value = 42, name = ""Cranberries"" }</c>), a dictionary, or a class instance.</param>")
                .AppendLine($"        {(addGetByKey ? "public" : "private")} static Translation GetByKey(string key, object? tokens = null)")
                .AppendLine("        {")
                .AppendLine($"            if ({className}.Translations == null)")
                .AppendLine($@"                throw new InvalidOperationException($""You must call {{nameof({className})}}.{{nameof({className}.Init)}} from the mod's entry method before reading translations."");")
                .AppendLine($"            return {className}.Translations.Get(key, tokens);")
                .AppendLine("        }");

                output
                .AppendLine("    }")
                .AppendLine("}")
                .AppendLine();

                // Add the source code to the compilation
                context.AddSource($"{className}.generated.cs", output.ToString());
            }
            catch (Exception ex)
            {
                this.LogException(context, ex);
            }
        }
Exemplo n.º 3
0
        public void setTranslationValues()
        {
            TranslationEntry.Clear();
            foreach (var k in TransResult.results)
            {
                if (k.lexicalEntries != null)
                {
                    foreach (var i in k.lexicalEntries)
                    {
                        var trans_item = new TranslateEntry();
                        trans_item.Type         = i.lexicalCategory;
                        trans_item.Examples     = "Examples: \n\n";
                        trans_item.Translations = "Translations: \n\n";
                        if (i.entries != null)
                        {
                            foreach (var j in i.entries)
                            {
                                if (j.senses != null)
                                {
                                    foreach (var y in j.senses)
                                    {
                                        if (y.translations != null)
                                        {
                                            foreach (var x in y.translations)
                                            {
                                                if (!trans_item.Translations.Contains(x.text))
                                                {
                                                    trans_item.Translations += x.text + "\n";
                                                }
                                            }
                                        }
                                        if (y.examples != null)
                                        {
                                            foreach (var example in y.examples)
                                            {
                                                if (example.translations != null)
                                                {
                                                    trans_item.Examples += example.text + "\n" + example.translations.ElementAt(0).text + "\n\n";
                                                }
                                            }
                                        }
                                        if (y.subsenses != null)
                                        {
                                            foreach (var x in y.subsenses)
                                            {
                                                if (x.translations != null)
                                                {
                                                    foreach (var trans in x.translations)
                                                    {
                                                        if (!trans_item.Translations.Contains(trans.text))
                                                        {
                                                            trans_item.Translations += trans.text + "\n";
                                                        }
                                                    }
                                                }
                                                if (x.examples != null)
                                                {
                                                    foreach (var example in x.examples)
                                                    {
                                                        if (example.translations != null)
                                                        {
                                                            trans_item.Examples += example.text + "\n" + example.translations.ElementAt(0).text + "\n\n";
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        TranslationEntry.Add(trans_item);
                    }
                }
            }
        }