• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Administrator's Toolkit VS plugin


Commit MetaInfo

Revisãocfaa5f6506f37db7a05ae4bcfa7aef5a6d737581 (tree)
Hora2020-12-17 10:39:47
Autormelchior <melchior@user...>
Commitermelchior

Mensagem de Log

D.I.Y. Multi-Lingual support, and to support i18n

Mudança Sumário

Diff

--- a/AdminToolkit/ATK_BasicFeatures.cs
+++ b/AdminToolkit/ATK_BasicFeatures.cs
@@ -86,8 +86,8 @@ namespace AdminToolkit
8686 //Annonce to all players that Admin\Moderator has arrived
8787
8888 StringBuilder adminMessage = new StringBuilder( );
89-
90- adminMessage.AppendFormat("<font color='{1}' weight='bold'>«{0}» {2}</font> Present.", byPlayer.Role.Name, byPlayer.Role.Color.Name, byPlayer.PlayerName);
89+
90+ adminMessage.Append(MultiLang.Get(byPlayer, @"atk:admin_present",byPlayer.Role.Name, byPlayer.Role.Color.Name, byPlayer.PlayerName));
9191
9292 ServerAPI.SendMessageToGroup(GlobalConstants.AllChatGroups, adminMessage.ToString( ), EnumChatType.AllGroups);
9393
@@ -104,7 +104,7 @@ namespace AdminToolkit
104104 var playerPos = byPlayer.Entity.Pos.AsBlockPos.Copy();
105105
106106 //No Localized Season/Hemispehere names?
107- string welcomebackMsg = Lang.Get(@"welcomeback-message",
107+ string welcomebackMsg = MultiLang.Get(byPlayer, @"atk:welcomeback-message",
108108 elapsedDays,
109109 ServerAPI.World.AllOnlinePlayers.Length,
110110 ServerAPI.World.Calendar.GetSeason(playerPos),
@@ -114,7 +114,7 @@ namespace AdminToolkit
114114 byPlayer.SendMessage(GlobalConstants.CurrentChatGroup, welcomebackMsg, EnumChatType.OthersMessage);
115115 }
116116 else {
117- string welcomeMsg = Lang.Get(@"welcome-message",
117+ string welcomeMsg = MultiLang.Get(byPlayer, @"atk:welcome-message",
118118 ServerAPI.World.Calendar.PrettyDate( )
119119 );
120120 byPlayer.SendMessage(GlobalConstants.CurrentChatGroup,welcomeMsg, EnumChatType.OthersMessage);
@@ -124,13 +124,6 @@ namespace AdminToolkit
124124
125125
126126 }
127-
128- /* Something like:
129-
130- string GetLang(string key, string langCode, params object[ ] parameters) //No fallback
131- string GetLang_Fallback(string key, string langCode, params object[ ] parameters) //Uses 'Local' language for missing key
132-
133- */
134127 }
135128 }
136129
--- a/AdminToolkit/AdminToolkit.csproj
+++ b/AdminToolkit/AdminToolkit.csproj
@@ -82,7 +82,7 @@
8282 <Compile Include="Commands\PingerCommand.cs" />
8383 <Compile Include="Commands\VariableSpawnpoints.cs" />
8484 <Compile Include="ATK_BasicFeatures.cs" />
85- <Compile Include="MultiLang.cs" />
85+ <Compile Include="Helpers\MultiLang.cs" />
8686 </ItemGroup>
8787 <ItemGroup>
8888 <Folder Include="VS_libs\" />
@@ -90,6 +90,7 @@
9090 <Folder Include="assets\" />
9191 <Folder Include="assets\atk\" />
9292 <Folder Include="assets\atk\lang\" />
93+ <Folder Include="Helpers\" />
9394 </ItemGroup>
9495 <ItemGroup>
9596 <None Include="modinfo.json">
@@ -100,6 +101,7 @@
100101 <None Include="assets\atk\lang\en.json">
101102 <CopyToOutputDirectory>Always</CopyToOutputDirectory>
102103 </None>
104+ <None Include="MultiLang.cs" />
103105 </ItemGroup>
104106 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
105107 </Project>
\ No newline at end of file
--- a/AdminToolkit/AdminToolkitMod.cs
+++ b/AdminToolkit/AdminToolkitMod.cs
@@ -101,6 +101,9 @@ namespace AdminToolkit
101101 PopulateAdminRoleTable( );
102102 PrepareServersideConfig( );
103103
104+ MultiLang.Load(Mod.Logger, ServerAPI.Assets, Mod.Info.ModID);
105+
106+
104107 if (this.CachedConfiguration.RuleRoleChangerEnabled) { this.ServerAPI.RegisterCommand(new RulesCommand(this.ServerAPI)); }
105108 this.ServerAPI.RegisterCommand(new AdminListingCommand(this.ServerAPI) );
106109 this.ServerAPI.RegisterCommand(new BackupCycleCommand(this.ServerAPI) );
--- a/AdminToolkit/Commands/AdminListingCommand.cs
+++ b/AdminToolkit/Commands/AdminListingCommand.cs
@@ -32,13 +32,13 @@ namespace AdminToolkit
3232 msgLine.AppendFormat("<font color='{2}'>[{0}]</font> -- \"{1}\" ", srvPlayer.Role.Name, playerName, srvPlayer.Role.Color.Name);
3333
3434 if (srvPlayer.ConnectionState == EnumClientState.Playing) {
35- msgLine.AppendFormat("IS: <font color='lime'>*{0}*</font>", srvPlayer.ConnectionState);
35+ msgLine.AppendFormat("· <font color='lime'>*{0}*</font>", srvPlayer.ConnectionState);
3636 } else {
37- msgLine.AppendFormat("IS: <font color='yellow'>{0}</font>", srvPlayer.ConnectionState);
37+ msgLine.AppendFormat("· <font color='yellow'>{0}</font>", srvPlayer.ConnectionState);
3838 }
3939
4040 if (srvPlayer.ServerData.CustomPlayerData.ContainsKey(AdminToolkit._lastLoginKey)) {
41- msgLine.AppendFormat(" Last Login: {0}", srvPlayer.ServerData.CustomPlayerData[AdminToolkit._lastLoginKey]);
41+ msgLine.AppendFormat("\tΔ : {0}", srvPlayer.ServerData.CustomPlayerData[AdminToolkit._lastLoginKey]);
4242 }
4343 msgLine.AppendLine( );
4444 }
--- a/AdminToolkit/Commands/RulesCommand.cs
+++ b/AdminToolkit/Commands/RulesCommand.cs
@@ -122,10 +122,10 @@ namespace AdminToolkit
122122
123123 PlayerAcceptsRulesAction( player);
124124 } else {
125- player.SendMessage(groupId, $"{player.PlayerName} ALREADY ACCEPTED RULES!", EnumChatType.CommandSuccess);
125+ player.SendMessage(groupId, MultiLang.Get(player, "atk:already-accept",player.PlayerName), EnumChatType.CommandSuccess);
126126 }
127127 } else {
128- player.SendMessage(groupId, $"{player.PlayerName} type in chat console: /rules {_acceptKeyword}", EnumChatType.CommandError);
128+ player.SendMessage(groupId, MultiLang.Get(player, "atk:type-chat-rules", player.PlayerName ,_acceptKeyword), EnumChatType.CommandError);
129129 }
130130
131131 } else {
@@ -139,7 +139,7 @@ namespace AdminToolkit
139139 }
140140 } else {
141141 //Subsitute rules?
142- player.SendMessage(groupId, $"* MISSING RULES FILE ({targetLocale})! *", EnumChatType.CommandError);
142+ player.SendMessage(groupId, MultiLang.Get(player, "atk:missing-rules", targetLocale), EnumChatType.CommandError);
143143 }
144144 }
145145 }
@@ -154,7 +154,7 @@ namespace AdminToolkit
154154 //For regular players
155155 if (RulesCommand.CheckRuleAccepted(byPlayer) == false) {
156156 //TODO: localize
157- byPlayer.SendMessage(GlobalConstants.CurrentChatGroup, "type ' /rules ' command for reading server rules.", EnumChatType.Notification);
157+ byPlayer.SendMessage(GlobalConstants.CurrentChatGroup, MultiLang.GetUnformatted(byPlayer,"atk:type-rules"), EnumChatType.Notification);
158158
159159 if (this.CachedConfiguration.RuleRoleChangerEnabled) {
160160 PlayerNeverAcceptedRulesAction(byPlayer);
@@ -165,7 +165,7 @@ namespace AdminToolkit
165165
166166 private void PlayerAcceptsRulesAction(IServerPlayer byPlayer )
167167 {
168- ServerAPI.BroadcastMessageToAllGroups($"{byPlayer.PlayerName} HAS ACCEPTED THE RULES!", EnumChatType.CommandSuccess);
168+ ServerAPI.BroadcastMessageToAllGroups(MultiLang.Get(byPlayer,"atk:accepted-rules", byPlayer.PlayerName), EnumChatType.CommandSuccess);
169169 byPlayer.ServerData.CustomPlayerData[_ruleAcceptKey] = true.ToString( );
170170 ServerAPI.Server.LogNotification($"Player:{byPlayer.PlayerName} UID: {byPlayer.PlayerUID} HAS ACCEPTED RULES @ {DateTime.Now.ToShortDateString( )}");
171171
@@ -176,7 +176,7 @@ namespace AdminToolkit
176176
177177 ServerAPI.Permissions.SetRole(byPlayer, normalRole.Code);
178178 Logger.Notification("Player {0} accepted the rules, and was promoted to role: {1}", byPlayer.PlayerName, byPlayer.Role.Name);
179- byPlayer.SendMessage(GlobalConstants.GeneralChatGroup, $"{byPlayer.PlayerName} have been promoted to: {byPlayer.Role.Name}", EnumChatType.OthersMessage);
179+ byPlayer.SendMessage(GlobalConstants.GeneralChatGroup, MultiLang.Get(byPlayer, "atk:promoted-to", byPlayer.PlayerName, byPlayer.Role.Name), EnumChatType.OthersMessage);
180180 } else {
181181 Logger.Debug("Role change process did not complete; not enabled or mis-configured");
182182 }
@@ -191,7 +191,7 @@ namespace AdminToolkit
191191
192192 ServerAPI.Permissions.SetRole(byPlayer, restrainRole.Code);
193193 Logger.Notification("Player {0} never accepted rules, and was demoted to role: {1}", byPlayer.PlayerName, byPlayer.Role.Name);
194- byPlayer.SendMessage(GlobalConstants.GeneralChatGroup, $"{byPlayer.PlayerName} have been demoted to: {byPlayer.Role.Name}", EnumChatType.OthersMessage);
194+ byPlayer.SendMessage(GlobalConstants.GeneralChatGroup, MultiLang.Get(byPlayer, "atk:demoted-to", byPlayer.PlayerName, byPlayer.Role.Name), EnumChatType.OthersMessage);
195195 }
196196 }
197197 }
--- a/AdminToolkit/Commands/VariableSpawnpoints.cs
+++ b/AdminToolkit/Commands/VariableSpawnpoints.cs
@@ -137,14 +137,7 @@ namespace AdminToolkit
137137
138138 private bool AddSpawnpoint(string name, Vec3i position)
139139 {
140- //Check position is 'safe'; 2~ blocks air, and solid block BELOW...
141- var surfaceBlock = ServerAPI.World.BlockAccessor.GetBlock(position.AsBlockPos);
142- var aboveBlock = ServerAPI.World.BlockAccessor.GetBlock(position.AddCopy(BlockFacing.UP).AsBlockPos);
143- var belowBlock = ServerAPI.World.BlockAccessor.GetBlock(position.AddCopy(BlockFacing.DOWN).AsBlockPos);
144-
145- if (belowBlock.MatterState == EnumMatterState.Solid &&
146- aboveBlock.BlockMaterial == EnumBlockMaterial.Air &&
147- surfaceBlock.BlockMaterial == EnumBlockMaterial.Air) {
140+ if (IsItSafe(position.AsBlockPos)) {
148141 //Appears OK...
149142 Logger.VerboseDebug($"Adding variable spawnpoint '{name}' @ {position}");
150143 var newSpawnpoint = new Spawnpoint(name, position);
@@ -159,6 +152,27 @@ namespace AdminToolkit
159152 return false;
160153 }
161154
155+ private bool IsItSafe(BlockPos position)
156+ {
157+ //Check position is 'safe'; 2~ blocks airish, and solid block BELOW...
158+ var surfaceBlock = ServerAPI.World.BlockAccessor.GetBlock(position);
159+ var aboveBlock = ServerAPI.World.BlockAccessor.GetBlock(position.AddCopy(BlockFacing.UP));
160+ var belowBlock = ServerAPI.World.BlockAccessor.GetBlock(position.AddCopy(BlockFacing.DOWN));
161+
162+ if (belowBlock.MatterState == EnumMatterState.Solid &&
163+ aboveBlock.BlockMaterial == EnumBlockMaterial.Air &&
164+ surfaceBlock.BlockMaterial == EnumBlockMaterial.Air
165+ || surfaceBlock.BlockMaterial == EnumBlockMaterial.Snow
166+ || surfaceBlock.BlockMaterial == EnumBlockMaterial.Liquid
167+ || surfaceBlock.BlockMaterial == EnumBlockMaterial.Leaves
168+ )
169+ {
170+ return true;
171+ }
172+
173+ return false;
174+ }
175+
162176 private bool RemoveSpawnpoint(string name)
163177 {
164178
--- /dev/null
+++ b/AdminToolkit/Helpers/MultiLang.cs
@@ -0,0 +1,120 @@
1+using System;
2+using System.Collections.Generic;
3+using System.Collections.ObjectModel;
4+using System.Linq;
5+using System.Text.RegularExpressions;
6+
7+using Newtonsoft.Json;
8+
9+using Vintagestory.API.Common;
10+using Vintagestory.API.Server;
11+using Vintagestory.Client.NoObf;
12+
13+namespace AdminToolkit
14+{
15+ public static class MultiLang
16+ {
17+ public static LanguageSet LanguageSets;
18+ public static string[ ] SupportedCodes { get; private set;}
19+
20+
21+ public static void Load(ILogger logger, IAssetManager ownAssetMgr, string domain)
22+ {
23+ #if DEBUG
24+ logger.VerboseDebug("Preparing to load Multi-Linugal data; for '{0}'", domain);
25+ #endif
26+
27+ List<IAssetOrigin> origins = ownAssetMgr.Origins;
28+ LanguageSets = new LanguageSet( );
29+
30+ GuiCompositeSettings.LanguageConfig[] supportedLangs = ownAssetMgr.Get<GuiCompositeSettings.LanguageConfig[]>(new AssetLocation("lang/languages.json"));
31+ SupportedCodes = supportedLangs.Select(sl => sl.Code).ToArray( );//{ "en", "de", "it", "fr", "pt-br", "ru" };
32+
33+ List<IAsset> languageAssets = ownAssetMgr.GetMany(@"lang/", domain, true);
34+ foreach (var asset in languageAssets) {
35+ try {
36+ LanguageSets.Add(new LangEntry(asset));
37+ #if DEBUG
38+ logger.VerboseDebug("Appended M.l. Dicts: with '{0}'", asset.Name);
39+ #endif
40+ } catch (Exception e) {
41+ logger.Error("Failed to process multi-lang file {0}: {1}", asset.Location, e);
42+ }
43+ }
44+ }
45+
46+
47+
48+ public static string Get(string langCode, string key, params object[] formaters)
49+ {
50+ if (LanguageSets.Contains(langCode))
51+ {
52+ LangEntry langD = LanguageSets[langCode];
53+ if (langD.LangEntries.ContainsKey(key)) {
54+ return string.Format(langD.LangEntries[key], formaters);
55+ }
56+ }
57+ return key;
58+ }
59+
60+ public static string Get(IServerPlayer byPlayerLang, string key, params object[ ] formaters)
61+ {
62+ if (LanguageSets.Contains(byPlayerLang.LanguageCode)) {
63+ LangEntry langD = LanguageSets[byPlayerLang.LanguageCode];
64+ if (langD.LangEntries.ContainsKey(key)) {
65+ return string.Format(langD.LangEntries[key], formaters);
66+ }
67+ }
68+ return key;
69+ }
70+
71+ public static string GetUnformatted(IServerPlayer byPlayerLang, string key)
72+ {
73+ if (LanguageSets.Contains(byPlayerLang.LanguageCode)) {
74+ LangEntry langD = LanguageSets[byPlayerLang.LanguageCode];
75+ if (langD.LangEntries.ContainsKey(key)) {
76+ return langD.LangEntries[key];
77+ }
78+ }
79+ return key;
80+ }
81+ }
82+
83+ public class LanguageSet : KeyedCollection<string, LangEntry>
84+ {
85+ protected override string GetKeyForItem(LangEntry item)
86+ {
87+ return item.Code;
88+ }
89+ }
90+
91+ public struct LangEntry
92+ {
93+ public Dictionary<string, string> LangEntries;
94+ //public Dictionary<string, KeyValuePair<Regex, string>> LangRegexes;
95+ //public Dictionary<string, string> LangStartsWith;
96+ public readonly string Code;
97+
98+ public LangEntry( string langCode = "en")
99+ {
100+ LangEntries = new Dictionary<string, string>( );
101+ //LangRegexes = new Dictionary<string, KeyValuePair<Regex, string>>( );
102+ //LangStartsWith = new Dictionary<string, string>( );
103+ Code = langCode;
104+ }
105+
106+ public LangEntry(IAsset langAsset)
107+ {
108+ if (langAsset.IsLoaded( )) {
109+ LangEntries = JsonConvert.DeserializeObject<Dictionary<string, string>>(langAsset.ToText( ));
110+ }
111+ else {
112+ LangEntries = new Dictionary<string, string>( );
113+ }
114+ //LangRegexes = new Dictionary<string, KeyValuePair<Regex, string>>( );
115+ //LangStartsWith = new Dictionary<string, string>( );
116+ Code = langAsset.Name.Split('.').First( );
117+ }
118+ }
119+}
120+
--- a/AdminToolkit/assets/atk/lang/en.json
+++ b/AdminToolkit/assets/atk/lang/en.json
@@ -1,12 +1,13 @@
11 {
2- "welcomeback-message": "Meantime... {0:F1} days have passed. {1} Players online. It is {2} in the {3}.",
3- "welcome-message":"In the year; {0}",
4- "display-rules":"Display server Rules",
5- "already-accept":"{0} ALREADY ACCEPTED RULES!",
6- "type-chat-rules":"{0} type in chat console: /rules {1}",
7- "missing-rules":"* MISSING RULES FILE ({0})! *",
8- "type-rules":"type ' /rules ' command for reading server rules.",
9- "accepted-rules":"{0} HAS ACCEPTED THE RULES!",
10- "promoted-to":"{0} have been promoted to: {1}",
11- "demoted-to":"{0} have been demoted to: {1}",
2+ "atk:admin_present":"<font color='{1}' weight='bold'>«{0}» {2}</font> Present.",
3+ "atk:welcomeback-message": "Meantime... {0:F1} days have passed. {1} Players online. It is {2} in the {3}.",
4+ "atk:welcome-message":"In the year; {0}",
5+ "atk:display-rules":"Display server Rules",
6+ "atk:already-accept":"{0} ALREADY ACCEPTED RULES!",
7+ "atk:type-chat-rules":"{0} type in chat console: /rules {1}",
8+ "atk:missing-rules":"* MISSING RULES FILE ({0})! *",
9+ "atk:type-rules":"type ' /rules ' command for reading server rules.",
10+ "atk:accepted-rules":"{0} HAS ACCEPTED THE RULES!",
11+ "atk:promoted-to":"{0} have been promoted to: {1}",
12+ "atk:demoted-to":"{0} have been demoted to: {1}",
1213 }
--- a/AdminToolkit/modinfo.json
+++ b/AdminToolkit/modinfo.json
@@ -6,7 +6,7 @@
66 "authors": ["Melchior", ],
77 "version": "0.3.6",
88 "dependencies": {
9- "game": "1.13.4"
9+ "game": "1.14.0"
1010 },
1111 "requiredonclient":false,
1212 "website": "https://osdn.net/users/melchior/pf/admintoolkit/"