• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ParadoxGameConverters / Fronter.NET / 21102980608

18 Jan 2026 12:09AM UTC coverage: 22.911% (+0.02%) from 22.891%
21102980608

Pull #931

github

web-flow
Merge 2182743db into 16c5617d5
Pull Request #931: Use AppContext.BaseDirectory for reading configuration files

143 of 770 branches covered (18.57%)

Branch coverage included in aggregate %.

3 of 7 new or added lines in 2 files covered. (42.86%)

49 existing lines in 1 file now uncovered.

718 of 2988 relevant lines covered (24.03%)

8.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

9.03
/Fronter.NET/Extensions/TranslationSource.cs
1
using commonItems;
2
using log4net;
3
using ReactiveUI;
4
using System;
5
using System.Collections.Generic;
6
using System.Globalization;
7
using System.IO;
8
using System.Text.RegularExpressions;
9

10
namespace Fronter.Extensions;
11

12
// idea based on https://gist.github.com/jakubfijalkowski/0771bfbd26ce68456d3e
13
internal sealed partial class TranslationSource : ReactiveObject {
14
        private static readonly ILog logger = LogManager.GetLogger("Translator");
1✔
15
        private TranslationSource() {
2✔
16
                string languagesPath = Path.Combine(AppContext.BaseDirectory, "languages.txt");
1✔
17
                if (!File.Exists(languagesPath)) {
2!
18
                        logger.Error("No languages dictionary found!");
1✔
19
                        return;
1✔
20
                }
21

22
                var languagesParser = new Parser();
×
23
                languagesParser.RegisterRegex(CommonRegexes.String, (langReader, langKey) => {
×
24
                        var cultureName = langReader.GetString();
×
25

×
26
                        CultureInfo cultureInfo;
×
27
                        try {
×
28
                                cultureInfo = CultureInfo.GetCultureInfo(cultureName);
×
29
                        } catch (CultureNotFoundException) {
×
30
                                logger.Debug($"Culture {cultureName} for language {langKey} not found!");
×
31
                                if (string.Equals(langKey, "english", StringComparison.OrdinalIgnoreCase)) {
×
32
                                        cultureInfo = CultureInfo.InvariantCulture;
×
33
                                } else {
×
34
                                        return;
×
35
                                }
×
36
                        }
×
37

×
38
                        languages.Add(langKey, cultureInfo);
×
39
                        LoadedLanguages.Add(langKey);
×
40
                });
×
41
                languagesParser.ParseFile(languagesPath);
×
42

43
                LoadLanguages();
×
44

NEW
45
                var fronterLanguagePath = Path.Combine(AppContext.BaseDirectory, "Configuration", "fronter-language.txt");
×
46
                if (File.Exists(fronterLanguagePath)) {
×
47
                        var parser = new Parser();
×
48
                        parser.RegisterKeyword("language", reader => CurrentLanguage = reader.GetString());
×
49
                        parser.ParseFile(fronterLanguagePath);
×
50
                }
×
51
        }
1✔
52

53
        public static TranslationSource Instance { get; } = new();
3✔
54

55
        public string Translate(string key) {
×
56
                string toReturn;
57

58
                if (translations.TryGetValue(key, out var dictionary)) {
×
59
                        if (dictionary.TryGetValue(CurrentLanguage, out var text)) {
×
60
                                toReturn = text;
×
61
                        } else if (dictionary.TryGetValue("english", out var englishText)) {
×
62
                                logger.Debug($"{CurrentLanguage} localization not found for key {key}, using english one");
×
63
                                toReturn = englishText;
×
64
                        } else {
×
65
                                logger.Debug($"{CurrentLanguage} localization not found for key {key}");
×
66
                                return string.Empty;
×
67
                        }
68
                } else {
×
69
                        return string.Empty;
×
70
                }
71

72
                toReturn = NewLineInStringRegex().Replace(toReturn, Environment.NewLine);
×
73
                return toReturn;
×
74
        }
×
75

76
        public string TranslateLanguage(string language) {
×
77
                return !languages.TryGetValue(language, out CultureInfo? cultureInfo) ? string.Empty : cultureInfo.NativeName;
×
78
        }
×
79

80
        public string this[string key] => Translate(key);
×
81

82
        public void SaveLanguage(string languageKey) {
×
83
                if (!LoadedLanguages.Contains(languageKey)) {
×
84
                        return;
×
85
                }
86
                CurrentLanguage = languageKey;
×
87

NEW
88
                var langFilePath = Path.Combine(AppContext.BaseDirectory, "Configuration", "fronter-language.txt");
×
89
                using var fs = new FileStream(langFilePath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
×
90
                using var writer = new StreamWriter(fs);
×
91
                writer.WriteLine($"language={languageKey}");
×
92
                writer.Close();
×
93
        }
×
94
        private void LoadLanguages() {
×
NEW
95
                var fileNames = SystemUtils.GetAllFilesInFolder(Path.Combine(AppContext.BaseDirectory, "Configuration"));
×
96

97
                foreach (var fileName in fileNames) {
×
98
                        if (!fileName.EndsWith(".yml", StringComparison.OrdinalIgnoreCase)) {
×
99
                                continue;
×
100
                        }
101

NEW
102
                        var langFilePath = Path.Combine(AppContext.BaseDirectory, "Configuration", fileName);
×
103
                        using var langFileStream = File.OpenRead(langFilePath);
×
104
                        using var langFileReader = new StreamReader(langFileStream);
×
105

106
                        var firstLine = langFileReader.ReadLine();
×
107
                        if (firstLine?.IndexOf("l_", StringComparison.Ordinal) != 0) {
×
108
                                logger.Error($"{langFilePath} is not a localization file!");
×
109
                                continue;
×
110
                        }
111
                        var pos = firstLine.IndexOf(':');
×
112
                        if (pos == -1) {
×
113
                                logger.Error($"Invalid localization language: {firstLine}");
×
114
                                continue;
×
115
                        }
116
                        var language = firstLine.Substring(2, pos - 2);
×
117

118
                        while (!langFileReader.EndOfStream) {
×
119
                                var line = langFileReader.ReadLine();
×
120
                                if (line is null) {
×
121
                                        break;
×
122
                                }
123

124
                                pos = line.IndexOf(':');
×
125
                                if (pos == -1) {
×
126
                                        continue;
×
127
                                }
128
                                var key = line[..pos].Trim();
×
129
                                pos = line.IndexOf('\"');
×
130
                                if (pos == -1) {
×
131
                                        logger.Error($"Invalid localization line: {line}");
×
132
                                        continue;
×
133
                                }
134
                                var secpos = line.LastIndexOf('\"');
×
135
                                if (secpos == -1) {
×
136
                                        logger.Error($"Invalid localization line: {line}");
×
137
                                        continue;
×
138
                                }
139
                                var text = line.Substring(pos + 1, secpos - pos - 1);
×
140

141
                                if (translations.TryGetValue(key, out var dictionary)) {
×
142
                                        dictionary[language] = text;
×
143
                                } else {
×
144
                                        var newDict = new Dictionary<string, string>(StringComparer.Ordinal) { [language] = text };
×
145
                                        translations.Add(key, newDict);
×
146
                                }
×
147
                        }
×
148
                }
×
149
        }
×
150

151
        public List<string> LoadedLanguages { get; } = [];
1✔
152
        private readonly Dictionary<string, CultureInfo> languages = [];
1✔
153
        private readonly Dictionary<string, Dictionary<string, string>> translations = []; // key, <language, text>
1✔
154

155
        public string CurrentLanguage {
156
                get;
×
157
                private set {
×
158
                        field = value;
×
159
                        this.RaisePropertyChanged(nameof(CurrentLanguage));
×
160
                        this.RaisePropertyChanged("Item");
×
161
                }
×
162
        } = "english";
1✔
163

164
        [GeneratedRegex(@"\\n")]
165
        private static partial Regex NewLineInStringRegex();
166
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc