重构I18n资源

This commit is contained in:
Hakoyu
2024-04-13 00:07:26 +08:00
parent 54d77018af
commit 4d64fdc766
52 changed files with 577 additions and 783 deletions

View File

@ -1,37 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HKW.HKWUtils.Observable;
namespace VPet.ModMaker.Models;
/// <summary>
/// I18n数据
/// </summary>
[DebuggerDisplay("{ID}, Count = {Datas.Count}")]
public class I18nData : ObservableObjectX
{
#region ID
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id = string.Empty;
/// <summary>
/// ID
/// </summary>
public string ID
{
get => _id;
set => SetProperty(ref _id, value);
}
#endregion
/// <summary>
/// 基于 <see cref="I18nHelper.Current.CultureNames"/> 的索引的数据列表
/// </summary>
public ObservableList<Func<INotifyPropertyChanged, string>> Datas { get; } = new();
}

View File

@ -1,42 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HKW.HKWUtils.Observable;
namespace VPet.ModMaker.Models;
// TODO: 更新事件
/// <summary>
/// I18n助手
/// </summary>
public class I18nHelper : ObservableObjectX
{
/// <summary>
/// 当前数据
/// </summary>
public static I18nHelper Current { get; set; } = new();
/// <summary>
/// 当前文化名称
/// </summary>
#region CultureName
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _cultureName;
public string CultureName
{
get => _cultureName;
set => SetProperty(ref _cultureName, value);
}
#endregion
/// <summary>
/// 文化列表
/// </summary>
public ObservableList<string> CultureNames { get; } = new();
}

View File

@ -1,97 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HKW.HKWUtils.Extensions;
using HKW.HKWUtils.Observable;
using Mapster;
namespace VPet.ModMaker.Models;
/// <summary>
/// I18n模型
/// </summary>
/// <typeparam name="T">类型</typeparam>
public class I18nModel<T> : ObservableObjectX
where T : ObservableObjectX, new()
{
/// <summary>
/// 当前I18n数据
/// </summary>
#region CurrentI18nData
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private T _currentI18nData;
[AdaptIgnore]
public T CurrentI18nData
{
get => _currentI18nData;
set => SetProperty(ref _currentI18nData, value);
}
#endregion
/// <summary>
/// 所有I18n数据
/// </summary>
[AdaptIgnore]
public Dictionary<string, T> I18nDatas { get; } = new();
public I18nModel()
{
I18nHelper.Current.PropertyChangedX += Current_PropertyChangedX;
I18nHelper.Current.CultureNames.ListChanged += CultureNames_ListChanged;
if (I18nHelper.Current.CultureNames.HasValue() is false)
return;
foreach (var item in I18nHelper.Current.CultureNames)
I18nDatas.Add(item, new());
CurrentI18nData = I18nDatas[I18nHelper.Current.CultureName];
}
private void CultureNames_ListChanged(
IObservableList<string> sender,
NotifyListChangedEventArgs<string> e
)
{
if (e.Action is ListChangeAction.Add && e.NewItems is not null)
{
foreach (var item in e.NewItems)
I18nDatas.TryAdd(item, new());
}
else if (e.Action is ListChangeAction.Remove && e.OldItems is not null)
{
foreach (var item in e.OldItems)
I18nDatas.Remove(item);
}
else if (
e.Action is ListChangeAction.Add
&& e.NewItems is not null
&& e.OldItems is not null
)
{
var newItem = e.NewItems.First();
var oldItem = e.OldItems.First();
if (I18nDatas.ContainsKey(oldItem) is false)
return;
I18nDatas[newItem] = I18nDatas[oldItem];
I18nDatas.Remove(oldItem);
}
}
/// <summary>
/// 文化改变
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Current_PropertyChangedX(object? sender, PropertyChangedXEventArgs e)
{
if (e.PropertyName == nameof(I18nHelper.CultureName))
{
if (e.NewValue is null)
CurrentI18nData = null!;
else if (I18nDatas.TryGetValue((string)e.NewValue, out var result))
CurrentI18nData = result;
}
}
}

View File

@ -94,14 +94,14 @@ public class ModLoader
public List<SelectText> SelectTexts { get; } = new(); public List<SelectText> SelectTexts { get; } = new();
/// <summary> /// <summary>
/// I18n数据 /// I18n资源
/// </summary> /// </summary>
public Dictionary<string, I18nModInfoModel> I18nDatas { get; } = new(); //public Dictionary<string, I18nModInfoModel> I18nDatas { get; } = new();
/// <summary> /// <summary>
/// 其它I18n数据 /// I18n资源
/// </summary> /// </summary>
public Dictionary<string, Dictionary<string, string>> OtherI18nDatas { get; } = new(); public Dictionary<string, Dictionary<string, string>> I18nDatas { get; } = new();
public ModLoader(DirectoryInfo path) public ModLoader(DirectoryInfo path)
{ {
@ -125,15 +125,15 @@ public class ModLoader
//MOD未加载时支持翻译 //MOD未加载时支持翻译
foreach (var line in modlps.FindAllLine("lang")) foreach (var line in modlps.FindAllLine("lang"))
{ {
var i18nData = new I18nModInfoModel(); if (I18nDatas.TryGetValue(line.Info, out var datas) is false)
datas = I18nDatas[line.Info] = new();
foreach (var sub in line) foreach (var sub in line)
{ {
if (sub.Name == Name) if (sub.Name == Name)
i18nData.Name = sub.Info; datas[Name] = sub.Info;
else if (sub.Name == Intro) else if (sub.Name == Intro)
i18nData.Description = sub.Info; datas[Intro] = sub.Info;
} }
I18nDatas.Add(line.Info, i18nData);
} }
DirectoryInfo? langDirectory = null; DirectoryInfo? langDirectory = null;
foreach (DirectoryInfo di in path.EnumerateDirectories()) foreach (DirectoryInfo di in path.EnumerateDirectories())
@ -236,17 +236,14 @@ public class ModLoader
} }
if (langDirectory is null) if (langDirectory is null)
return; return;
foreach (DirectoryInfo dis in langDirectory.EnumerateDirectories()) foreach (var dis in langDirectory.EnumerateDirectories())
{ {
OtherI18nDatas.Add(dis.Name, new()); I18nDatas.TryAdd(dis.Name, new());
foreach (FileInfo fi in dis.EnumerateFiles("*.lps")) foreach (FileInfo fi in dis.EnumerateFiles("*.lps"))
{ {
var lps = new LPS(File.ReadAllText(fi.FullName)); var lps = new LPS(File.ReadAllText(fi.FullName));
foreach (var item in lps) foreach (var item in lps)
{ I18nDatas[dis.Name].TryAdd(item.Name, item.Info);
if (OtherI18nDatas[dis.Name].ContainsKey(item.Name) is false)
OtherI18nDatas[dis.Name].TryAdd(item.Name, item.Info);
}
} }
} }
} }

View File

@ -14,6 +14,8 @@ namespace VPet.ModMaker.Models;
/// </summary> /// </summary>
public class ModMakeHistory : IEquatable<ModMakeHistory> public class ModMakeHistory : IEquatable<ModMakeHistory>
{ {
public ModMakeHistory() { }
/// <summary> /// <summary>
/// 图片 /// 图片
/// </summary> /// </summary>
@ -28,7 +30,7 @@ public class ModMakeHistory : IEquatable<ModMakeHistory>
/// <summary> /// <summary>
/// 路径 /// 路径
/// </summary> /// </summary>
private string _path = string.Empty; private string _sourcePath = string.Empty;
/// <summary> /// <summary>
/// 资源路径 /// 资源路径
@ -36,11 +38,13 @@ public class ModMakeHistory : IEquatable<ModMakeHistory>
[Line(ignoreCase: true)] [Line(ignoreCase: true)]
public string SourcePath public string SourcePath
{ {
get => _path; get => _sourcePath;
set set
{ {
_path = value; if (string.IsNullOrWhiteSpace(_sourcePath) is false)
var imagePath = Path.Combine(_path, "icon.png"); Image?.CloseStream();
_sourcePath = value;
var imagePath = Path.Combine(_sourcePath, "icon.png");
if (File.Exists(imagePath)) if (File.Exists(imagePath))
Image = NativeUtils.LoadImageToMemoryStream(imagePath); Image = NativeUtils.LoadImageToMemoryStream(imagePath);
} }

View File

@ -35,7 +35,7 @@ public class AnimeModel : ObservableObjectX, ICloneable<AnimeModel>
private string _id = string.Empty; private string _id = string.Empty;
/// <summary> /// <summary>
/// Id /// ID
/// </summary> /// </summary>
public string ID public string ID
{ {

View File

@ -9,6 +9,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using HKW.HKWUtils.Extensions;
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using VPet_Simulator.Core; using VPet_Simulator.Core;
using static VPet_Simulator.Core.GraphInfo; using static VPet_Simulator.Core.GraphInfo;
@ -103,7 +104,7 @@ public class AnimeTypeModel : ObservableObjectX
private string _id = string.Empty; private string _id = string.Empty;
/// <summary> /// <summary>
/// Id /// ID
/// </summary> /// </summary>
public string ID public string ID
{ {
@ -202,7 +203,7 @@ public class AnimeTypeModel : ObservableObjectX
public AnimeTypeModel(GraphInfo.GraphType graphType, string path) public AnimeTypeModel(GraphInfo.GraphType graphType, string path)
{ {
Name = Path.GetFileName(path); Name = Path.GetFileName(path);
// 为带有名字的类型设置Id // 为带有名字的类型设置ID
if (graphType.IsHasNameAnime()) if (graphType.IsHasNameAnime())
ID = $"{graphType}_{Name}"; ID = $"{graphType}_{Name}";
else else
@ -643,8 +644,8 @@ public class AnimeTypeModel : ObservableObjectX
static void SaveAnimes(string animePath, ObservableList<AnimeModel> animes) static void SaveAnimes(string animePath, ObservableList<AnimeModel> animes)
{ {
Directory.CreateDirectory(animePath); Directory.CreateDirectory(animePath);
foreach (var anime in animes.EnumerateIndex()) foreach ((var index, var anime) in animes.EnumerateIndex())
SaveImages(Path.Combine(animePath, anime.Index.ToString()), anime.Value); SaveImages(Path.Combine(animePath, index.ToString()), anime);
} }
} }
@ -656,10 +657,10 @@ public class AnimeTypeModel : ObservableObjectX
static void SaveImages(string imagesPath, AnimeModel model) static void SaveImages(string imagesPath, AnimeModel model)
{ {
Directory.CreateDirectory(imagesPath); Directory.CreateDirectory(imagesPath);
foreach (var image in model.Images.EnumerateIndex()) foreach ((var index, var image) in model.Images.EnumerateIndex())
{ {
image.Value.Image.SaveToPng( image.Image.SaveToPng(
Path.Combine(imagesPath, $"{model.ID}_{image.Index:000}_{image.Value.Duration}.png") Path.Combine(imagesPath, $"{model.ID}_{index:000}_{image.Duration}.png")
); );
} }
} }

View File

@ -17,9 +17,14 @@ namespace VPet.ModMaker.Models;
/// <summary> /// <summary>
/// 点击文本模型 /// 点击文本模型
/// </summary> /// </summary>
public class ClickTextModel : I18nModel<I18nClickTextModel> public class ClickTextModel : ObservableObjectX
{ {
public ClickTextModel() { } public ClickTextModel()
{
ModInfoModel.Current.I18nResource.I18nObjectInfos.Add(
new(this, OnPropertyChanged, [(nameof(ID), ID, nameof(Text), true)])
);
}
public ClickTextModel(ClickTextModel clickText) public ClickTextModel(ClickTextModel clickText)
: this() : this()
@ -37,9 +42,6 @@ public class ClickTextModel : I18nModel<I18nClickTextModel>
Drink = clickText.Drink.Clone(); Drink = clickText.Drink.Clone();
Feel = clickText.Feel.Clone(); Feel = clickText.Feel.Clone();
Strength = clickText.Strength.Clone(); Strength = clickText.Strength.Clone();
foreach (var item in clickText.I18nDatas)
I18nDatas[item.Key] = item.Value.Clone();
CurrentI18nData = I18nDatas[I18nHelper.Current.CultureName];
} }
public ClickTextModel(ClickText clickText) public ClickTextModel(ClickText clickText)
@ -121,6 +123,15 @@ public class ClickTextModel : I18nModel<I18nClickTextModel>
} }
#endregion #endregion
#region I18nData
[AdaptIgnore]
public string Text
{
get => ModInfoModel.Current.I18nResource.GetCurrentCultureDataOrDefault(ID, string.Empty);
set => ModInfoModel.Current.I18nResource.SetCurrentCultureData(ID, value);
}
#endregion
#region Working #region Working
[DebuggerBrowsable(DebuggerBrowsableState.Never)] [DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _working = string.Empty; private string _working = string.Empty;

View File

@ -7,6 +7,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using HKW.HKWUtils.Extensions;
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using LinePutScript; using LinePutScript;
using LinePutScript.Localization.WPF; using LinePutScript.Localization.WPF;
@ -271,10 +272,10 @@ public class FoodAnimeTypeModel : ObservableObjectX
var animePath = Path.Combine(path, Name); var animePath = Path.Combine(path, Name);
if ( if (
Directory.Exists(animePath) Directory.Exists(animePath)
&& HappyAnimes.Count == 0 && HappyAnimes.HasValue() is false
&& NomalAnimes.Count == 0 && NomalAnimes.HasValue() is false
&& PoorConditionAnimes.Count == 0 && PoorConditionAnimes.HasValue() is false
&& IllAnimes.Count == 0 && IllAnimes.HasValue() is false
) )
{ {
Directory.Delete(animePath, true); Directory.Delete(animePath, true);
@ -303,15 +304,15 @@ public class FoodAnimeTypeModel : ObservableObjectX
) )
{ {
var modeAnimePath = Path.Combine(animePath, mode.ToString()); var modeAnimePath = Path.Combine(animePath, mode.ToString());
foreach (var anime in animes.EnumerateIndex()) foreach ((var index, var anime) in animes.EnumerateIndex())
{ {
var indexPath = Path.Combine(modeAnimePath, anime.Index.ToString()); var indexPath = Path.Combine(modeAnimePath, index.ToString());
Directory.CreateDirectory(indexPath); Directory.CreateDirectory(indexPath);
var infoFile = Path.Combine(indexPath, ModMakerInfo.InfoFile); var infoFile = Path.Combine(indexPath, ModMakerInfo.InfoFile);
var frontLayName = $"{Name.ToLower()}_{FrontLayName}_{anime.Index}"; var frontLayName = $"{Name.ToLower()}_{FrontLayName}_{index}";
var backLayName = $"{Name.ToLower()}_{BackLayName}_{anime.Index}"; var backLayName = $"{Name.ToLower()}_{BackLayName}_{index}";
SaveInfoFile(infoFile, frontLayName, backLayName, anime.Value, mode); SaveInfoFile(infoFile, frontLayName, backLayName, anime, mode);
SaveImages(anime.Value, indexPath); SaveImages(anime, indexPath);
} }
} }
@ -328,22 +329,16 @@ public class FoodAnimeTypeModel : ObservableObjectX
var backLayPath = Path.Combine(indexPath, BackLayName); var backLayPath = Path.Combine(indexPath, BackLayName);
Directory.CreateDirectory(frontLayPath); Directory.CreateDirectory(frontLayPath);
Directory.CreateDirectory(backLayPath); Directory.CreateDirectory(backLayPath);
foreach (var frontImage in anime.FrontImages.EnumerateIndex()) foreach ((var index, var frontImage) in anime.FrontImages.EnumerateIndex())
{ {
frontImage.Value.Image.SaveToPng( frontImage.Image.SaveToPng(
Path.Combine( Path.Combine(frontLayPath, $"{anime.ID}_{index:000}_{frontImage.Duration}.png")
frontLayPath,
$"{anime.ID}_{frontImage.Index:000}_{frontImage.Value.Duration}.png"
)
); );
} }
foreach (var backImage in anime.BackImages.EnumerateIndex()) foreach ((var index, var backImage) in anime.BackImages.EnumerateIndex())
{ {
backImage.Value.Image.SaveToPng( backImage.Image.SaveToPng(
Path.Combine( Path.Combine(backLayPath, $"{anime.ID}_{backImage:000}_{backImage.Duration}.png")
backLayPath,
$"{anime.ID}_{backImage.Index:000}_{backImage.Value.Duration}.png"
)
); );
} }
} }
@ -376,10 +371,10 @@ public class FoodAnimeTypeModel : ObservableObjectX
new Sub("mode", mode.ToString()), new Sub("mode", mode.ToString()),
new Sub("graph", Name) new Sub("graph", Name)
}; };
foreach (var foodLocation in anime.FoodLocations.EnumerateIndex()) foreach ((var index, var foodLocation) in anime.FoodLocations.EnumerateIndex())
{ {
var sub = new Sub($"a{foodLocation.Index}"); var sub = new Sub($"a{index}");
sub.info = foodLocation.Value.ToString(); sub.info = foodLocation.ToString();
line.Add(sub); line.Add(sub);
} }
line.Add(new Sub(FrontLayName, frontLayName)); line.Add(new Sub(FrontLayName, frontLayName));

View File

@ -21,11 +21,21 @@ namespace VPet.ModMaker.Models;
/// <summary> /// <summary>
/// 食物模型 /// 食物模型
/// </summary> /// </summary>
public class FoodModel : I18nModel<I18nFoodModel> public class FoodModel : ObservableObjectX
{ {
public FoodModel() public FoodModel()
{ {
PropertyChangedX += FoodModel_PropertyChangedX; PropertyChangedX += FoodModel_PropertyChangedX;
ModInfoModel.Current.I18nResource.I18nObjectInfos.Add(
new(
this,
OnPropertyChanged,
[
(nameof(ID), ID, nameof(Name), true),
(nameof(DescriptionID), DescriptionID, nameof(Description), true)
]
)
);
} }
private static FrozenSet<string> _notifyReferencePrice = FrozenSet.ToFrozenSet( private static FrozenSet<string> _notifyReferencePrice = FrozenSet.ToFrozenSet(
@ -54,9 +64,6 @@ public class FoodModel : I18nModel<I18nFoodModel>
{ {
model.Adapt(this); model.Adapt(this);
Image = model.Image?.CloneStream(); Image = model.Image?.CloneStream();
foreach (var item in model.I18nDatas)
I18nDatas[item.Key] = item.Value.Clone();
CurrentI18nData = I18nDatas[I18nHelper.Current.CultureName];
} }
public FoodModel(Food food) public FoodModel(Food food)
@ -108,6 +115,26 @@ public class FoodModel : I18nModel<I18nFoodModel>
} }
#endregion #endregion
#region I18nData
[AdaptIgnore]
public string Name
{
get => ModInfoModel.Current.I18nResource.GetCurrentCultureDataOrDefault(ID, string.Empty);
set => ModInfoModel.Current.I18nResource.SetCurrentCultureData(ID, value);
}
[AdaptIgnore]
public string Description
{
get =>
ModInfoModel.Current.I18nResource.GetCurrentCultureDataOrDefault(
DescriptionID,
string.Empty
);
set => ModInfoModel.Current.I18nResource.SetCurrentCultureData(DescriptionID, value);
}
#endregion
#region Graph #region Graph
[DebuggerBrowsable(DebuggerBrowsableState.Never)] [DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _graph = string.Empty; private string _graph = string.Empty;
@ -310,7 +337,7 @@ public class FoodModel : I18nModel<I18nFoodModel>
//}; //};
} }
public void RefreshId() public void RefreshID()
{ {
DescriptionID = $"{ID}_{nameof(DescriptionID)}"; DescriptionID = $"{ID}_{nameof(DescriptionID)}";
} }
@ -318,34 +345,10 @@ public class FoodModel : I18nModel<I18nFoodModel>
public void Close() public void Close()
{ {
Image?.CloseStream(); Image?.CloseStream();
var item = ModInfoModel.Current.I18nResource.I18nObjectInfos.FirstOrDefault(i =>
i.Source == this
);
if (item is not null)
ModInfoModel.Current.I18nResource.I18nObjectInfos.Remove(item);
} }
} }
public class I18nFoodModel : ObservableObjectX, ICloneable<I18nFoodModel>
{
#region Name
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _name = string.Empty;
public string Name
{
get => _name;
set => SetProperty(ref _name, value);
}
#endregion
#region Description
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _description = string.Empty;
public string Description
{
get => _description;
set => SetProperty(ref _description, value);
}
#endregion
public I18nFoodModel Clone() => this.Adapt<I18nFoodModel>();
object ICloneable.Clone() => Clone();
}

View File

@ -16,18 +16,19 @@ namespace VPet.ModMaker.Models;
/// <summary> /// <summary>
/// 低状态文本 /// 低状态文本
/// </summary> /// </summary>
public class LowTextModel : I18nModel<I18nLowTextModel> public class LowTextModel : ObservableObjectX
{ {
public LowTextModel() { } public LowTextModel()
{
ModInfoModel.Current.I18nResource.I18nObjectInfos.Add(
new(this, OnPropertyChanged, [(nameof(ID), ID, nameof(Text), true)])
);
}
public LowTextModel(LowTextModel lowText) public LowTextModel(LowTextModel lowText)
: this() : this()
{ {
lowText.Adapt(this); lowText.Adapt(this);
foreach (var item in lowText.I18nDatas)
I18nDatas[item.Key] = item.Value.Clone();
CurrentI18nData = I18nDatas[I18nHelper.Current.CultureName];
} }
public LowTextModel(LowText lowText) public LowTextModel(LowText lowText)
@ -69,6 +70,15 @@ public class LowTextModel : I18nModel<I18nLowTextModel>
} }
#endregion #endregion
#region I18nData
[AdaptIgnore]
public string Text
{
get => ModInfoModel.Current.I18nResource.GetCurrentCultureDataOrDefault(ID, string.Empty);
set => ModInfoModel.Current.I18nResource.SetCurrentCultureData(ID, value);
}
#endregion
#region Mode #region Mode
[DebuggerBrowsable(DebuggerBrowsableState.Never)] [DebuggerBrowsable(DebuggerBrowsableState.Never)]
private LowText.ModeType _mode; private LowText.ModeType _mode;
@ -119,24 +129,3 @@ public class LowTextModel : I18nModel<I18nLowTextModel>
return this.Adapt<LowText>(); return this.Adapt<LowText>();
} }
} }
public class I18nLowTextModel : ObservableObjectX, ICloneable<I18nLowTextModel>
{
#region Text
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _text = string.Empty;
public string Text
{
get => _text;
set => SetProperty(ref _text, value);
}
#endregion
public I18nLowTextModel Clone()
{
return this.Adapt<I18nLowTextModel>();
}
object ICloneable.Clone() => Clone();
}

View File

@ -4,6 +4,7 @@ using System.Collections.ObjectModel;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -26,10 +27,11 @@ namespace VPet.ModMaker.Models;
/// <summary> /// <summary>
/// 模组信息模型 /// 模组信息模型
/// </summary> /// </summary>
public class ModInfoModel : I18nModel<I18nModInfoModel> public class ModInfoModel : ObservableObjectX
{ {
public ModInfoModel() public ModInfoModel()
{ {
Current = this;
PropertyChanged += ModInfoModel_PropertyChanged; PropertyChanged += ModInfoModel_PropertyChanged;
Pets.CollectionChanged += Pets_CollectionChanged; Pets.CollectionChanged += Pets_CollectionChanged;
} }
@ -104,25 +106,22 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
LoadAnime(petModel, p); LoadAnime(petModel, p);
} }
//loader.Pets.First().Name = "TestMainPet";
//Pets.Insert(0, new(loader.Pets.First(), true));
// 插入本体宠物 // 插入本体宠物
foreach (var pet in ModMakerInfo.MainPets) foreach (var pet in ModMakerInfo.MainPets)
{ {
// 确保Id不重复 // 确保ID不重复
if (Pets.All(i => i.ID != pet.Key)) if (Pets.All(i => i.ID != pet.Key))
Pets.Insert(0, pet.Value); Pets.Insert(0, pet.Value);
} }
// 载入本地化 // 载入本地化模组信息
foreach (var lang in loader.I18nDatas) //foreach (var lang in loader.I18nDatas)
I18nDatas.Add(lang.Key, lang.Value); // I18nDatas.Add(lang.Key, lang.Value);
OtherI18nDatas = loader.OtherI18nDatas; //OtherI18nDatas = loader.I18nDatas;
LoadI18nDatas(); LoadI18nDatas(loader);
RefreshAllId(); RefreshAllID();
if (I18nHelper.Current.CultureNames.HasValue()) if (I18nResource.CultureDatas.HasValue())
RefreshID(); RefreshID();
} }
@ -143,6 +142,21 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
/// </summary> /// </summary>
public static ModInfoModel Current { get; set; } = new(); public static ModInfoModel Current { get; set; } = new();
public I18nResource<string, string> I18nResource { get; } = new();
#region I18nData
public string Name
{
get => I18nResource.GetCurrentCultureDataOrDefault(ID, string.Empty);
set => I18nResource.SetCurrentCultureData(ID, value);
}
public string Description
{
get => I18nResource.GetCurrentCultureDataOrDefault(DescriptionID, string.Empty);
set => I18nResource.SetCurrentCultureData(DescriptionID, value);
}
#endregion
#region AutoSetFoodPrice #region AutoSetFoodPrice
[DebuggerBrowsable(DebuggerBrowsableState.Never)] [DebuggerBrowsable(DebuggerBrowsableState.Never)]
private bool _autoSetFoodPrice; private bool _autoSetFoodPrice;
@ -173,12 +187,12 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
#region ModInfo #region ModInfo
/// <summary> /// <summary>
/// 作者Id /// 作者ID
/// </summary> /// </summary>
public long AuthorID { get; } public long AuthorID { get; }
/// <summary> /// <summary>
/// 项目Id /// 项目ID
/// </summary> /// </summary>
public ulong ItemID { get; } public ulong ItemID { get; }
@ -187,7 +201,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
private string _id = string.Empty; private string _id = string.Empty;
/// <summary> /// <summary>
/// Id /// ID
/// </summary> /// </summary>
public string ID public string ID
{ {
@ -198,15 +212,15 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
#region DescriptionID #region DescriptionID
[DebuggerBrowsable(DebuggerBrowsableState.Never)] [DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _descriptionId = string.Empty; private string _descriptionID = string.Empty;
/// <summary> /// <summary>
/// 描述Id /// 描述ID
/// </summary> /// </summary>
public string DescriptionID public string DescriptionID
{ {
get => _descriptionId; get => _descriptionID;
set => SetProperty(ref _descriptionId, value); set => SetProperty(ref _descriptionID, value);
} }
#endregion #endregion
@ -322,15 +336,6 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
} }
#endregion #endregion
/// <summary>
/// 其它I18n数据
/// </summary>
public Dictionary<string, Dictionary<string, string>> OtherI18nDatas { get; } = new();
/// <summary>
/// 需要保存的I18n数据
/// </summary>
public static Dictionary<string, Dictionary<string, string>> SaveI18nDatas { get; } = new();
#endregion #endregion
private void Pets_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) private void Pets_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
@ -439,100 +444,121 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
/// <summary> /// <summary>
/// 加载本地化数据 /// 加载本地化数据
/// </summary> /// </summary>
private void LoadI18nDatas() private void LoadI18nDatas(ModLoader modLoader)
{ {
foreach (var lang in I18nDatas.Keys.Union(OtherI18nDatas.Keys)) if (modLoader.I18nDatas.HasValue() is false)
{
if (I18nHelper.Current.CultureNames.Contains(lang) is false)
I18nHelper.Current.CultureNames.Add(lang);
}
if (I18nHelper.Current.CultureNames.Count == 0)
return; return;
I18nHelper.Current.CultureName = I18nHelper.Current.CultureNames.First(); foreach (var cultureDatas in modLoader.I18nDatas)
foreach (var i18nData in OtherI18nDatas)
{ {
LoadFoodI18nData(i18nData.Key, i18nData.Value); var culture = CultureInfo.GetCultureInfo(cultureDatas.Key);
LoadLowTextI18nData(i18nData.Key, i18nData.Value); I18nResource.AddCulture(culture);
LoadClickTextI18nData(i18nData.Key, i18nData.Value); foreach (var data in cultureDatas.Value)
LoadSelectTextI18nData(i18nData.Key, i18nData.Value); I18nResource.AddCultureData(culture, data.Key, data.Value);
LoadPetI18nData(i18nData.Key, i18nData.Value);
} }
if (I18nResource.SetCurrentCulture(CultureInfo.CurrentCulture) is false)
I18nResource.SetCurrentCulture(I18nResource.CultureDatas.First().Key);
I18nResource.I18nObjectInfos.Add(
new(
this,
OnPropertyChanged,
[
(nameof(ID), ID, nameof(Name), true),
(nameof(DescriptionID), DescriptionID, nameof(Description), true)
]
)
);
//foreach (var lang in I18nDatas.Keys.Union(OtherI18nDatas.Keys))
//{
// if (I18nHelper.Current.CultureNames.Contains(lang) is false)
// I18nHelper.Current.CultureNames.Add(lang);
//}
//if (I18nHelper.Current.CultureNames.Count == 0)
// return;
//I18nHelper.Current.CultureName = I18nHelper.Current.CultureNames.First();
//foreach (var i18nData in OtherI18nDatas)
//{
// LoadFoodI18nData(i18nData.Key, i18nData.Value);
// LoadLowTextI18nData(i18nData.Key, i18nData.Value);
// LoadClickTextI18nData(i18nData.Key, i18nData.Value);
// LoadSelectTextI18nData(i18nData.Key, i18nData.Value);
// LoadPetI18nData(i18nData.Key, i18nData.Value);
//}
} }
private void LoadFoodI18nData(string key, Dictionary<string, string> i18nData) //private void LoadFoodI18nData(string key, Dictionary<string, string> i18nData)
//{
// foreach (var food in Foods)
// {
// if (food.I18nDatas.TryGetValue(key, out var data) is false)
// continue;
// if (i18nData.TryGetValue(food.ID, out var name))
// data.Name = name;
// if (i18nData.TryGetValue(food.DescriptionID, out var description))
// data.Description = description;
// }
//}
//private void LoadLowTextI18nData(string key, Dictionary<string, string> i18nData)
//{
// foreach (var lowText in LowTexts)
// {
// if (lowText.I18nDatas.TryGetValue(key, out var data) is false)
// continue;
// if (i18nData.TryGetValue(lowText.ID, out var text))
// data.Text = text;
// }
//}
//private void LoadClickTextI18nData(string key, Dictionary<string, string> i18nData)
//{
// foreach (var clickText in ClickTexts)
// {
// if (clickText.I18nDatas.TryGetValue(key, out var data) is false)
// continue;
// if (i18nData.TryGetValue(clickText.ID, out var text))
// data.Text = text;
// }
//}
//private void LoadSelectTextI18nData(string key, Dictionary<string, string> i18nData)
//{
// foreach (var selectText in SelectTexts)
// {
// if (selectText.I18nDatas.TryGetValue(key, out var data) is false)
// continue;
// if (i18nData.TryGetValue(selectText.ID, out var text))
// data.Text = text;
// if (i18nData.TryGetValue(selectText.ChooseID, out var choose))
// data.Choose = choose;
// }
//}
//private void LoadPetI18nData(string key, Dictionary<string, string> i18nData)
//{
// foreach (var pet in Pets)
// {
// if (pet.I18nDatas.TryGetValue(key, out var data) is false)
// continue;
// if (i18nData.TryGetValue(pet.ID, out var name))
// data.Name = name;
// if (i18nData.TryGetValue(pet.PetNameID, out var petName))
// data.PetName = petName;
// if (i18nData.TryGetValue(pet.DescriptionID, out var description))
// data.Description = description;
// foreach (var work in pet.Works)
// {
// if (work.I18nDatas.TryGetValue(key, out var workData) is false)
// continue;
// if (i18nData.TryGetValue(work.ID, out var workName))
// workData.Name = workName;
// }
// }
//}
private void RefreshAllID()
{ {
foreach (var food in Foods) foreach (var food in Foods)
{ food.RefreshID();
if (food.I18nDatas.TryGetValue(key, out var data) is false)
continue;
if (i18nData.TryGetValue(food.ID, out var name))
data.Name = name;
if (i18nData.TryGetValue(food.DescriptionID, out var description))
data.Description = description;
}
}
private void LoadLowTextI18nData(string key, Dictionary<string, string> i18nData)
{
foreach (var lowText in LowTexts)
{
if (lowText.I18nDatas.TryGetValue(key, out var data) is false)
continue;
if (i18nData.TryGetValue(lowText.ID, out var text))
data.Text = text;
}
}
private void LoadClickTextI18nData(string key, Dictionary<string, string> i18nData)
{
foreach (var clickText in ClickTexts)
{
if (clickText.I18nDatas.TryGetValue(key, out var data) is false)
continue;
if (i18nData.TryGetValue(clickText.ID, out var text))
data.Text = text;
}
}
private void LoadSelectTextI18nData(string key, Dictionary<string, string> i18nData)
{
foreach (var selectText in SelectTexts)
{
if (selectText.I18nDatas.TryGetValue(key, out var data) is false)
continue;
if (i18nData.TryGetValue(selectText.ID, out var text))
data.Text = text;
if (i18nData.TryGetValue(selectText.ChooseID, out var choose))
data.Choose = choose;
}
}
private void LoadPetI18nData(string key, Dictionary<string, string> i18nData)
{
foreach (var pet in Pets)
{
if (pet.I18nDatas.TryGetValue(key, out var data) is false)
continue;
if (i18nData.TryGetValue(pet.ID, out var name))
data.Name = name;
if (i18nData.TryGetValue(pet.PetNameID, out var petName))
data.PetName = petName;
if (i18nData.TryGetValue(pet.DescriptionID, out var description))
data.Description = description;
foreach (var work in pet.Works)
{
if (work.I18nDatas.TryGetValue(key, out var workData) is false)
continue;
if (i18nData.TryGetValue(work.ID, out var workName))
workData.Name = workName;
}
}
}
private void RefreshAllId()
{
foreach (var food in Foods)
food.RefreshId();
foreach (var selectText in SelectTexts) foreach (var selectText in SelectTexts)
selectText.RefreshID(); selectText.RefreshID();
foreach (var pet in Pets) foreach (var pet in Pets)
@ -554,7 +580,6 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
/// <param name="path">路径</param> /// <param name="path">路径</param>
public void SaveTo(string path) public void SaveTo(string path)
{ {
SaveI18nDatas.Clear();
// 保存模型信息 // 保存模型信息
SaveModInfo(path); SaveModInfo(path);
// 保存模组数据 // 保存模组数据
@ -563,7 +588,6 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
SaveText(path); SaveText(path);
SaveI18nData(path); SaveI18nData(path);
SaveImage(path); SaveImage(path);
SaveI18nDatas.Clear();
} }
/// <summary> /// <summary>
@ -576,10 +600,6 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
if (File.Exists(modInfoFile) is false) if (File.Exists(modInfoFile) is false)
File.Create(modInfoFile).Close(); File.Create(modInfoFile).Close();
SaveI18nDatas.Clear();
foreach (var cultureName in I18nHelper.Current.CultureNames)
SaveI18nDatas.Add(cultureName, new());
var lps = new LPS() var lps = new LPS()
{ {
new Line("vupmod", ID) new Line("vupmod", ID)
@ -593,13 +613,23 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
new Line("itemid", ItemID.ToString()), new Line("itemid", ItemID.ToString()),
new Line("cachedate", DateTime.Now.Date.ToString("s")) new Line("cachedate", DateTime.Now.Date.ToString("s"))
}; };
foreach (var cultureName in I18nHelper.Current.CultureNames) foreach (var cultureData in Current.I18nResource.CultureDatas)
{ {
lps.Add( lps.Add(
new Line("lang", cultureName) new Line("cultureDatas", cultureData.Key.Name)
{ {
new Sub(ID, I18nDatas[cultureName].Name), new Sub(
new Sub(DescriptionID, I18nDatas[cultureName].Description), ID,
I18nResource.GetCultureDataOrDefault(cultureData.Key.Name, ID, string.Empty)
),
new Sub(
DescriptionID,
I18nResource.GetCultureDataOrDefault(
cultureData.Key.Name,
DescriptionID,
string.Empty
)
),
} }
); );
} }
@ -646,15 +676,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
File.Create(foodFile).Close(); File.Create(foodFile).Close();
var lps = new LPS(); var lps = new LPS();
foreach (var food in Foods) foreach (var food in Foods)
{
lps.Add(LPSConvert.SerializeObjectToLine<Line>(food.ToFood(), "food")); lps.Add(LPSConvert.SerializeObjectToLine<Line>(food.ToFood(), "food"));
foreach (var cultureName in I18nHelper.Current.CultureNames)
{
SaveI18nDatas[cultureName].TryAdd(food.ID, food.I18nDatas[cultureName].Name);
SaveI18nDatas[cultureName]
.TryAdd(food.DescriptionID, food.I18nDatas[cultureName].Description);
}
}
File.WriteAllText(foodFile, lps.ToString()); File.WriteAllText(foodFile, lps.ToString());
} }
@ -690,15 +712,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
File.Create(textFile).Close(); File.Create(textFile).Close();
var lps = new LPS(); var lps = new LPS();
foreach (var text in SelectTexts) foreach (var text in SelectTexts)
{
lps.Add(LPSConvert.SerializeObjectToLine<Line>(text.ToSelectText(), "SelectText")); lps.Add(LPSConvert.SerializeObjectToLine<Line>(text.ToSelectText(), "SelectText"));
foreach (var cultureName in I18nHelper.Current.CultureNames)
{
SaveI18nDatas[cultureName].TryAdd(text.ID, text.I18nDatas[cultureName].Text);
SaveI18nDatas[cultureName]
.TryAdd(text.ChooseID, text.I18nDatas[cultureName].Choose);
}
}
File.WriteAllText(textFile, lps.ToString()); File.WriteAllText(textFile, lps.ToString());
} }
@ -714,13 +728,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
File.Create(textFile).Close(); File.Create(textFile).Close();
var lps = new LPS(); var lps = new LPS();
foreach (var text in LowTexts) foreach (var text in LowTexts)
{
lps.Add(LPSConvert.SerializeObjectToLine<Line>(text.ToLowText(), "lowfoodtext")); lps.Add(LPSConvert.SerializeObjectToLine<Line>(text.ToLowText(), "lowfoodtext"));
foreach (var cultureName in I18nHelper.Current.CultureNames)
{
SaveI18nDatas[cultureName].TryAdd(text.ID, text.I18nDatas[cultureName].Text);
}
}
File.WriteAllText(textFile, lps.ToString()); File.WriteAllText(textFile, lps.ToString());
} }
@ -736,32 +744,26 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
File.Create(textFile).Close(); File.Create(textFile).Close();
var lps = new LPS(); var lps = new LPS();
foreach (var text in ClickTexts) foreach (var text in ClickTexts)
{
lps.Add(LPSConvert.SerializeObjectToLine<Line>(text.ToClickText(), "clicktext")); lps.Add(LPSConvert.SerializeObjectToLine<Line>(text.ToClickText(), "clicktext"));
foreach (var cultureName in I18nHelper.Current.CultureNames)
{
SaveI18nDatas[cultureName].TryAdd(text.ID, text.I18nDatas[cultureName].Text);
}
}
File.WriteAllText(textFile, lps.ToString()); File.WriteAllText(textFile, lps.ToString());
} }
#endregion #endregion
/// <summary> /// <summary>
/// 保存I18n数据 /// 保存I18n资源
/// </summary> /// </summary>
/// <param name="path">路径</param> /// <param name="path">路径</param>
private void SaveI18nData(string path) private void SaveI18nData(string path)
{ {
var langPath = Path.Combine(path, "lang"); var langPath = Path.Combine(path, "lang");
Directory.CreateDirectory(langPath); Directory.CreateDirectory(langPath);
foreach (var cultureName in I18nHelper.Current.CultureNames) foreach (var cultureData in I18nResource.CultureDatas)
{ {
var culturePath = Path.Combine(langPath, cultureName); var culturePath = Path.Combine(langPath, cultureData.Key.Name);
Directory.CreateDirectory(culturePath); Directory.CreateDirectory(culturePath);
var cultureFile = Path.Combine(culturePath, $"{cultureName}.lps"); var cultureFile = Path.Combine(culturePath, $"{cultureData.Key.Name}.lps");
File.Create(cultureFile).Close(); File.Create(cultureFile).Close();
var lps = new LPS(); var lps = new LPS();
foreach (var data in SaveI18nDatas[cultureName]) foreach (var data in cultureData.Value)
lps.Add(new Line(data.Key, data.Value)); lps.Add(new Line(data.Key, data.Value));
File.WriteAllText(cultureFile, lps.ToString()); File.WriteAllText(cultureFile, lps.ToString());
} }
@ -806,7 +808,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
// 保存模型信息 // 保存模型信息
SaveModInfo(path); SaveModInfo(path);
// 保存文化数据 // 保存文化数据
var langPath = Path.Combine(path, "lang"); var langPath = Path.Combine(path, "cultureDatas");
Directory.CreateDirectory(langPath); Directory.CreateDirectory(langPath);
foreach (var cultureName in cultures) foreach (var cultureName in cultures)
{ {
@ -828,26 +830,26 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
} }
} }
public class I18nModInfoModel : ObservableObjectX //public class I18nModInfoModel : ObservableObjectX
{ //{
#region Name // #region Name
[DebuggerBrowsable(DebuggerBrowsableState.Never)] // [DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _name = string.Empty; // private string _name = string.Empty;
public string Name // public string Name
{ // {
get => _name; // get => _name;
set => SetProperty(ref _name, value); // set => SetProperty(ref _name, value);
} // }
#endregion // #endregion
#region Description // #region Description
[DebuggerBrowsable(DebuggerBrowsableState.Never)] // [DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _description = string.Empty; // private string _description = string.Empty;
public string Description // public string Description
{ // {
get => _description; // get => _description;
set => SetProperty(ref _description, value); // set => SetProperty(ref _description, value);
} // }
#endregion // #endregion
} //}

View File

@ -23,13 +23,24 @@ namespace VPet.ModMaker.Models;
/// <summary> /// <summary>
/// 宠物模型 /// 宠物模型
/// </summary> /// </summary>
public class PetModel : I18nModel<I18nPetInfoModel> public class PetModel : ObservableObjectX
{ {
public PetModel() public PetModel()
{ {
PropertyChanged += PetModel_PropertyChanged; PropertyChanged += PetModel_PropertyChanged;
Animes.PropertyChanged += Animes_PropertyChanged; Animes.PropertyChanged += Animes_PropertyChanged;
FoodAnimes.PropertyChanged += FoodAnimes_PropertyChanged; FoodAnimes.PropertyChanged += FoodAnimes_PropertyChanged;
ModInfoModel.Current.I18nResource.I18nObjectInfos.Add(
new(
this,
OnPropertyChanged,
[
(nameof(ID), ID, nameof(Name), true),
(nameof(PetNameID), PetNameID, nameof(Name), true),
(nameof(DescriptionID), DescriptionID, nameof(Description), true)
]
)
);
} }
private void PetModel_PropertyChanged(object? sender, PropertyChangedEventArgs e) private void PetModel_PropertyChanged(object? sender, PropertyChangedEventArgs e)
@ -54,10 +65,6 @@ public class PetModel : I18nModel<I18nPetInfoModel>
RaisePoint = model.RaisePoint.Clone(); RaisePoint = model.RaisePoint.Clone();
foreach (var work in model.Works) foreach (var work in model.Works)
Works.Add(work); Works.Add(work);
foreach (var item in model.I18nDatas)
I18nDatas[item.Key] = item.Value.Clone();
CurrentI18nData = I18nDatas[I18nHelper.Current.CultureName];
} }
public PetModel(PetLoader loader, bool fromMain = false) public PetModel(PetLoader loader, bool fromMain = false)
@ -185,6 +192,37 @@ public class PetModel : I18nModel<I18nPetInfoModel>
} }
#endregion #endregion
#region I18nData
[AdaptIgnore]
public string Name
{
get => ModInfoModel.Current.I18nResource.GetCurrentCultureDataOrDefault(ID, string.Empty);
set => ModInfoModel.Current.I18nResource.SetCurrentCultureData(ID, value);
}
[AdaptIgnore]
public string PetName
{
get =>
ModInfoModel.Current.I18nResource.GetCurrentCultureDataOrDefault(
PetNameID,
string.Empty
);
set => ModInfoModel.Current.I18nResource.SetCurrentCultureData(PetNameID, value);
}
[AdaptIgnore]
public string Description
{
get =>
ModInfoModel.Current.I18nResource.GetCurrentCultureDataOrDefault(
DescriptionID,
string.Empty
);
set => ModInfoModel.Current.I18nResource.SetCurrentCultureData(DescriptionID, value);
}
#endregion
#region Tags #region Tags
[DebuggerBrowsable(DebuggerBrowsableState.Never)] [DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _tags = string.Empty; private string _tags = string.Empty;
@ -344,16 +382,17 @@ public class PetModel : I18nModel<I18nPetInfoModel>
/// <param name="path">路径</param> /// <param name="path">路径</param>
public void Save(string path) public void Save(string path)
{ {
foreach (var cultureName in I18nHelper.Current.CultureNames) // TODO
{ //foreach (var cultureName in I18nHelper.Current.CultureNames)
ModInfoModel.SaveI18nDatas[cultureName].TryAdd(ID, I18nDatas[cultureName].Name); //{
ModInfoModel // ModInfoModel.SaveI18nDatas[cultureName].TryAdd(ID, I18nDatas[cultureName].Name);
.SaveI18nDatas[cultureName] // ModInfoModel
.TryAdd(PetNameID, I18nDatas[cultureName].PetName); // .SaveI18nDatas[cultureName]
ModInfoModel // .TryAdd(PetNameID, I18nDatas[cultureName].PetName);
.SaveI18nDatas[cultureName] // ModInfoModel
.TryAdd(DescriptionID, I18nDatas[cultureName].Description); // .SaveI18nDatas[cultureName]
} // .TryAdd(DescriptionID, I18nDatas[cultureName].Description);
//}
var petFile = Path.Combine(path, $"{ID}.lps"); var petFile = Path.Combine(path, $"{ID}.lps");
if (File.Exists(petFile) is false) if (File.Exists(petFile) is false)
File.Create(petFile).Close(); File.Create(petFile).Close();
@ -400,13 +439,14 @@ public class PetModel : I18nModel<I18nPetInfoModel>
{ {
foreach (var work in Works) foreach (var work in Works)
{ {
lps.Add(LPSConvert.SerializeObjectToLine<Line>(work.ToWork(), "work")); //TODO
foreach (var cultureName in I18nHelper.Current.CultureNames) //lps.Add(LPSConvert.SerializeObjectToLine<Line>(work.ToWork(), "work"));
{ //foreach (var cultureName in I18nHelper.Current.CultureNames)
ModInfoModel //{
.SaveI18nDatas[cultureName] // ModInfoModel
.TryAdd(work.ID, work.I18nDatas[cultureName].Name); // .SaveI18nDatas[cultureName]
} // .TryAdd(work.ID, work.I18nDatas[cultureName].Name);
//}
} }
} }
@ -545,51 +585,6 @@ public class PetModel : I18nModel<I18nPetInfoModel>
#endregion #endregion
} }
public class I18nPetInfoModel : ObservableObjectX, ICloneable<I18nPetInfoModel>
{
#region Name
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _name = string.Empty;
public string Name
{
get => _name;
set => SetProperty(ref _name, value);
}
#endregion
#region PetName
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _petName = string.Empty;
public string PetName
{
get => _petName;
set => SetProperty(ref _petName, value);
}
#endregion
#region Description
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _description = string.Empty;
public string Description
{
get => _description;
set => SetProperty(ref _description, value);
}
#endregion
public I18nPetInfoModel Clone()
{
var result = new I18nPetInfoModel();
result.Name = Name;
result.PetName = PetName;
result.Description = Description;
return result;
}
object ICloneable.Clone() => Clone();
}
public class ObservableMultiStateRectangleLocation public class ObservableMultiStateRectangleLocation
: ObservableObjectX, : ObservableObjectX,
IEquatable<ObservableMultiStateRectangleLocation>, IEquatable<ObservableMultiStateRectangleLocation>,

View File

@ -16,9 +16,21 @@ namespace VPet.ModMaker.Models;
/// <summary> /// <summary>
/// 选择文本模型 /// 选择文本模型
/// </summary> /// </summary>
public class SelectTextModel : I18nModel<I18nSelectTextModel> public class SelectTextModel : ObservableObjectX
{ {
public SelectTextModel() { } public SelectTextModel()
{
ModInfoModel.Current.I18nResource.I18nObjectInfos.Add(
new(
this,
OnPropertyChanged,
[
(nameof(ID), ID, nameof(Text), true),
(nameof(ChooseID), ChooseID, nameof(Choose), true)
]
)
);
}
public SelectTextModel(SelectTextModel model) public SelectTextModel(SelectTextModel model)
: this() : this()
@ -37,10 +49,6 @@ public class SelectTextModel : I18nModel<I18nSelectTextModel>
Drink = model.Drink.Clone(); Drink = model.Drink.Clone();
Feel = model.Feel.Clone(); Feel = model.Feel.Clone();
Strength = model.Strength.Clone(); Strength = model.Strength.Clone();
foreach (var item in model.I18nDatas)
I18nDatas[item.Key] = item.Value.Clone();
CurrentI18nData = I18nDatas[I18nHelper.Current.CultureName];
} }
public SelectTextModel(SelectText text) public SelectTextModel(SelectText text)
@ -126,6 +134,26 @@ public class SelectTextModel : I18nModel<I18nSelectTextModel>
} }
#endregion #endregion
#region I18nData
[AdaptIgnore]
public string Text
{
get => ModInfoModel.Current.I18nResource.GetCurrentCultureDataOrDefault(ID, string.Empty);
set => ModInfoModel.Current.I18nResource.SetCurrentCultureData(ID, value);
}
[AdaptIgnore]
public string Choose
{
get =>
ModInfoModel.Current.I18nResource.GetCurrentCultureDataOrDefault(
ChooseID,
string.Empty
);
set => ModInfoModel.Current.I18nResource.SetCurrentCultureData(ChooseID, value);
}
#endregion
/// <summary> /// <summary>
/// 宠物状态 /// 宠物状态
/// </summary> /// </summary>
@ -212,34 +240,3 @@ public class SelectTextModel : I18nModel<I18nSelectTextModel>
}; };
} }
} }
public class I18nSelectTextModel : ObservableObjectX, ICloneable<I18nSelectTextModel>
{
#region Choose
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _choose = string.Empty;
public string Choose
{
get => _choose;
set => SetProperty(ref _choose, value);
}
#endregion
#region Text
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _text = string.Empty;
public string Text
{
get => _text;
set => SetProperty(ref _text, value);
}
#endregion
public I18nSelectTextModel Clone()
{
return this.Adapt<I18nSelectTextModel>();
}
object ICloneable.Clone() => Clone();
}

View File

@ -18,11 +18,14 @@ namespace VPet.ModMaker.Models;
/// <summary> /// <summary>
/// 工作模型 /// 工作模型
/// </summary> /// </summary>
public class WorkModel : I18nModel<I18nWorkModel> public class WorkModel : ObservableObjectX
{ {
public WorkModel() public WorkModel()
{ {
PropertyChanged += WorkModel_PropertyChanged; PropertyChanged += WorkModel_PropertyChanged;
ModInfoModel.Current.I18nResource.I18nObjectInfos.Add(
new(this, OnPropertyChanged, [(nameof(ID), ID, nameof(Name), true)])
);
} }
private static readonly FrozenSet<string> _notifyIsOverLoad = FrozenSet.ToFrozenSet( private static readonly FrozenSet<string> _notifyIsOverLoad = FrozenSet.ToFrozenSet(
@ -71,9 +74,6 @@ public class WorkModel : I18nModel<I18nWorkModel>
Width = model.Width; Width = model.Width;
//Image = model.Image?.CloneStream(); //Image = model.Image?.CloneStream();
foreach (var item in model.I18nDatas)
I18nDatas[item.Key] = item.Value.Clone();
CurrentI18nData = I18nDatas[I18nHelper.Current.CultureName];
} }
public WorkModel(VPet_Simulator.Core.GraphHelper.Work work) public WorkModel(VPet_Simulator.Core.GraphHelper.Work work)
@ -111,12 +111,12 @@ public class WorkModel : I18nModel<I18nWorkModel>
public static FrozenSet<VPet_Simulator.Core.GraphHelper.Work.WorkType> WorkTypes { get; } = public static FrozenSet<VPet_Simulator.Core.GraphHelper.Work.WorkType> WorkTypes { get; } =
Enum.GetValues<VPet_Simulator.Core.GraphHelper.Work.WorkType>().ToFrozenSet(); Enum.GetValues<VPet_Simulator.Core.GraphHelper.Work.WorkType>().ToFrozenSet();
#region Id #region ID
[DebuggerBrowsable(DebuggerBrowsableState.Never)] [DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id = string.Empty; private string _id = string.Empty;
/// <summary> /// <summary>
/// Id /// ID
/// </summary> /// </summary>
public string ID public string ID
{ {
@ -125,6 +125,15 @@ public class WorkModel : I18nModel<I18nWorkModel>
} }
#endregion #endregion
#region I18nData
[AdaptIgnore]
public string Name
{
get => ModInfoModel.Current.I18nResource.GetCurrentCultureDataOrDefault(ID, string.Empty);
set => ModInfoModel.Current.I18nResource.SetCurrentCultureData(ID, value);
}
#endregion
#region Graph #region Graph
[DebuggerBrowsable(DebuggerBrowsableState.Never)] [DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _graph = string.Empty; private string _graph = string.Empty;
@ -450,28 +459,10 @@ public class WorkModel : I18nModel<I18nWorkModel>
public void Close() public void Close()
{ {
//Image?.CloseStream(); //Image?.CloseStream();
var item = ModInfoModel.Current.I18nResource.I18nObjectInfos.FirstOrDefault(i =>
i.Source == this
);
if (item is not null)
ModInfoModel.Current.I18nResource.I18nObjectInfos.Remove(item);
} }
} }
public class I18nWorkModel : ObservableObjectX, ICloneable<I18nWorkModel>
{
#region Name
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _name = string.Empty;
public string Name
{
get => _name;
set => SetProperty(ref _name, value);
}
#endregion
public I18nWorkModel Clone()
{
var result = new I18nWorkModel();
result.Name = Name;
return result;
}
object ICloneable.Clone() => Clone();
}

View File

@ -46,9 +46,9 @@
</ControlTemplate> </ControlTemplate>
<ControlTemplate x:Key="ListBox_ShowLangs" TargetType="ListBox"> <ControlTemplate x:Key="ListBox_ShowLangs" TargetType="ListBox">
<ListBox <ListBox
ItemsSource="{Binding I18nData.CultureNames}" ItemsSource="{Binding I18nResource.CultureDatas.ObservableKeys}"
ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto"
SelectedItem="{Binding I18nData.CultureName}"> SelectedItem="{Binding I18nResource.CurrentCulture}">
<ListBox.ItemContainerStyle> <ListBox.ItemContainerStyle>
<Style BasedOn="{StaticResource {x:Type ListBoxItem}}" TargetType="ListBoxItem"> <Style BasedOn="{StaticResource {x:Type ListBoxItem}}" TargetType="ListBoxItem">
<Setter Property="Content" Value="{Binding}" /> <Setter Property="Content" Value="{Binding}" />

View File

@ -258,19 +258,6 @@ public static class NativeExtensions
return weakReference.TryGetTarget(out var t) ? t : null; return weakReference.TryGetTarget(out var t) ? t : null;
} }
/// <summary>
/// 枚举出带有索引值的枚举值
/// </summary>
/// <typeparam name="T">值类型</typeparam>
/// <param name="collection">集合</param>
/// <returns>带有索引的枚举值</returns>
public static IEnumerable<ItemInfo<T>> EnumerateIndex<T>(this IEnumerable<T> collection)
{
var index = 0;
foreach (var item in collection)
yield return new(index++, item);
}
public static void SetDataContext<T>(this Window window, Action? closedAction = null) public static void SetDataContext<T>(this Window window, Action? closedAction = null)
where T : new() where T : new()
{ {
@ -304,36 +291,3 @@ public static class NativeExtensions
}; };
} }
} }
/// <summary>
/// 项信息
/// </summary>
/// <typeparam name="T"></typeparam>
[DebuggerDisplay("[{Index}, {Value}]")]
public readonly struct ItemInfo<T>
{
/// <summary>
/// 索引值
/// </summary>
public int Index { get; }
/// <summary>
/// 值
/// </summary>
public T Value { get; }
/// <inheritdoc/>
/// <param name="value">值</param>
/// <param name="index">索引值</param>
public ItemInfo(int index, T value)
{
Index = index;
Value = value;
}
/// <inheritdoc/>
public override string ToString()
{
return $"[{Index}, {Value}]";
}
}

View File

@ -10,25 +10,26 @@
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<UseWPF>true</UseWPF> <UseWPF>true</UseWPF>
<LangVersion>preview</LangVersion> <LangVersion>preview</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Resources\food.png" /> <EmbeddedResource Include="Resources\food.png" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="VPet-Simulator.Core" Version="1.1.0.1" /> <PackageReference Include="VPet-Simulator.Core" Version="1.1.0.4" />
<PackageReference Include="VPet-Simulator.Windows.Interface" Version="1.1.0.1" /> <PackageReference Include="VPet-Simulator.Windows.Interface" Version="1.1.0.5" />
<PackageReference Include="LinePutScript" Version="1.11.6" /> <PackageReference Include="LinePutScript" Version="1.11.6" />
<PackageReference Include="LinePutScript.Localization.WPF" Version="1.0.6" /> <PackageReference Include="LinePutScript.Localization.WPF" Version="1.0.6" />
<PackageReference Include="Ookii.Dialogs.Wpf" Version="5.0.1" /> <PackageReference Include="Ookii.Dialogs.Wpf" Version="5.0.1" />
<PackageReference Include="Panuon.WPF" Version="1.1.0" /> <PackageReference Include="Panuon.WPF" Version="1.1.0" />
<PackageReference Include="Panuon.WPF.UI" Version="1.2.1.1" /> <PackageReference Include="Panuon.WPF.UI" Version="1.2.1.2" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" /> <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" /> <PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="HKW.Utils" Version="1.2.6" /> <PackageReference Include="HKW.Utils" Version="1.2.13" />
<PackageReference Include="HKW.WPF" Version="1.0.3" /> <PackageReference Include="HKW.WPF" Version="1.0.4" />
<PackageReference Include="Mapster" Version="7.4.0" /> <PackageReference Include="Mapster" Version="7.4.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -13,7 +13,10 @@ namespace VPet.ModMaker.ViewModels.ModEdit.ClickTextEdit;
public class ClickTextEditWindowVM : ObservableObjectX public class ClickTextEditWindowVM : ObservableObjectX
{ {
public static I18nHelper I18nData => I18nHelper.Current; /// <summary>
/// I18n资源
/// </summary>
public static I18nResource<string, string> I18nResource => ModInfoModel.Current.I18nResource;
#region Value #region Value
/// <summary> /// <summary>

View File

@ -25,7 +25,11 @@ public class FoodEditWindowVM : ObservableObjectX
} }
public static ModInfoModel ModInfo => ModInfoModel.Current; public static ModInfoModel ModInfo => ModInfoModel.Current;
public static I18nHelper I18nData => I18nHelper.Current;
/// <summary>
/// I18n资源
/// </summary>
public static I18nResource<string, string> I18nResource => ModInfoModel.Current.I18nResource;
#region Property #region Property
public FoodModel? OldFood { get; set; } public FoodModel? OldFood { get; set; }

View File

@ -7,6 +7,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using Mapster;
using VPet.ModMaker.Models; using VPet.ModMaker.Models;
namespace VPet.ModMaker.ViewModels.ModEdit.I18nEdit; namespace VPet.ModMaker.ViewModels.ModEdit.I18nEdit;
@ -67,12 +68,12 @@ public class I18nEditWindowVM : ObservableObjectX { }
// #endregion // #endregion
// /// <summary> // /// <summary>
// /// 全部I18n数据 (ID, I18nData) // /// 全部I18n资源 (ID, I18nData)
// /// </summary> // /// </summary>
// public Dictionary<string, I18nData> AllI18nDatas { get; } = new(); // public Dictionary<string, I18nData> AllI18nDatas { get; } = new();
// /// <summary> // /// <summary>
// /// 全部的I18n数据 // /// 全部的I18n资源
// /// </summary> // /// </summary>
// #region ShowI18nDatas // #region ShowI18nDatas
// [DebuggerBrowsable(DebuggerBrowsableState.Never)] // [DebuggerBrowsable(DebuggerBrowsableState.Never)]
@ -144,7 +145,7 @@ public class I18nEditWindowVM : ObservableObjectX { }
// #region LoadData // #region LoadData
// /// <summary> // /// <summary>
// /// 初始化I18n数据 // /// 初始化I18n资源
// /// </summary> // /// </summary>
// /// <param name="model"></param> // /// <param name="model"></param>
// public void InitializeI18nData(ModInfoModel model) // public void InitializeI18nData(ModInfoModel model)
@ -360,11 +361,19 @@ public class I18nEditWindowVM : ObservableObjectX { }
// /// <param name="id"></param> // /// <param name="id"></param>
// /// <param name="i18nModel"></param> // /// <param name="i18nModel"></param>
// /// <param name="i18nValue"></param> // /// <param name="i18nValue"></param>
// private void AddData<T>(string id, Func<T,string> getValue) // private void AddData<TViewModel, TI18nModel>(
// where T : , new() // TViewModel viewModel,
// Func<TViewModel, string> getID,
// Action<TViewModel, string> setID,
// Func<TI18nModel, string> getI18nData,
// Action<TI18nModel, string> setI18nData
// )
// where TViewModel : I18nModel<TI18nModel>
// where TI18nModel : ObservableObjectX, new()
// { // {
// if (AllI18nDatas.TryGetValue(id, out var outData)) // if (AllI18nDatas.TryGetValue(getID(viewModel), out var outData))
// { // {
// AdaptMemberAttribute
// foreach (var culture in I18nHelper.Current.CultureNames.EnumerateIndex()) // foreach (var culture in I18nHelper.Current.CultureNames.EnumerateIndex())
// { // {
// if (outData.Datas[culture.Index].Group is null) // if (outData.Datas[culture.Index].Group is null)
@ -379,7 +388,7 @@ public class I18nEditWindowVM : ObservableObjectX { }
// else // else
// { // {
// var data = new I18nData(); // var data = new I18nData();
// data.ID = id.Value; // data.ID = getID(viewModel);
// foreach (var culture in I18nHelper.Current.CultureNames) // foreach (var culture in I18nHelper.Current.CultureNames)
// data.Datas.Add(i18nValue(i18nModel.I18nDatas[culture])); // data.Datas.Add(i18nValue(i18nModel.I18nDatas[culture]));
// I18nDatas.Add(data); // I18nDatas.Add(data);
@ -417,7 +426,7 @@ public class I18nEditWindowVM : ObservableObjectX { }
// } // }
// /// <summary> // /// <summary>
// /// 删除I18n数据 // /// 删除I18n资源
// /// </summary> // /// </summary>
// /// <typeparam name="T"></typeparam> // /// <typeparam name="T"></typeparam>
// /// <param name="id"></param> // /// <param name="id"></param>
@ -452,7 +461,7 @@ public class I18nEditWindowVM : ObservableObjectX { }
// } // }
// /// <summary> // /// <summary>
// /// 替换I18n数据 // /// 替换I18n资源
// /// </summary> // /// </summary>
// /// <typeparam name="T"></typeparam> // /// <typeparam name="T"></typeparam>
// /// <param name="id"></param> // /// <param name="id"></param>

View File

@ -13,7 +13,10 @@ namespace VPet.ModMaker.ViewModels.ModEdit.LowTextEdit;
public class LowTextEditWindowVM : ObservableObjectX public class LowTextEditWindowVM : ObservableObjectX
{ {
public static I18nHelper I18nData => I18nHelper.Current; /// <summary>
/// I18n资源
/// </summary>
public static I18nResource<string, string> I18nResource => ModInfoModel.Current.I18nResource;
#region Value #region Value
public LowTextModel? OldLowText { get; set; } public LowTextModel? OldLowText { get; set; }

View File

@ -11,6 +11,7 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using HKW.HKWUtils.Extensions;
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using LinePutScript.Localization.WPF; using LinePutScript.Localization.WPF;
using Microsoft.Win32; using Microsoft.Win32;
@ -59,9 +60,9 @@ public class ModEditWindowVM : ObservableObjectX
#endregion #endregion
/// <summary> /// <summary>
/// I18n数据 /// I18n资源
/// </summary> /// </summary>
public static I18nHelper I18nData => I18nHelper.Current; public I18nResource<string, string> I18nResource => ModInfo.I18nResource;
#endregion #endregion
#region Command #region Command
@ -163,9 +164,8 @@ public class ModEditWindowVM : ObservableObjectX
window.ShowDialog(); window.ShowDialog();
if (window.IsCancel) if (window.IsCancel)
return; return;
I18nHelper.Current.CultureNames.Add(window.ViewModel.Culture); ModInfoModel.Current.I18nResource.AddCulture(window.ViewModel.Culture);
if (I18nHelper.Current.CultureNames.Count == 1) ModInfoModel.Current.I18nResource.SetCurrentCulture(window.ViewModel.Culture);
I18nHelper.Current.CultureName = window.ViewModel.Culture;
} }
/// <summary> /// <summary>
@ -179,8 +179,7 @@ public class ModEditWindowVM : ObservableObjectX
window.ShowDialog(); window.ShowDialog();
if (window.IsCancel) if (window.IsCancel)
return; return;
I18nHelper.Current.CultureNames[I18nHelper.Current.CultureNames.IndexOf(oldCulture)] = ModInfoModel.Current.I18nResource.ReplaceCulture(oldCulture, window.ViewModel.Culture);
window.ViewModel.Culture;
} }
/// <summary> /// <summary>
@ -197,7 +196,7 @@ public class ModEditWindowVM : ObservableObjectX
) is MessageBoxResult.No ) is MessageBoxResult.No
) )
return; return;
I18nHelper.Current.CultureNames.Remove(oldCulture); ModInfoModel.Current.I18nResource.RemoveCulture(oldCulture);
} }
public void SetMainCultureCommand_ExecuteCommand(string culture) public void SetMainCultureCommand_ExecuteCommand(string culture)
@ -212,30 +211,31 @@ public class ModEditWindowVM : ObservableObjectX
is not MessageBoxResult.Yes is not MessageBoxResult.Yes
) )
return; return;
ModInfo.I18nDatas[culture].Name = ModInfo.ID; // TODO
ModInfo.I18nDatas[culture].Description = ModInfo.DescriptionID; //ModInfo.I18nDatas[culture].Name = ModInfo.ID;
foreach (var food in ModInfo.Foods) //ModInfo.I18nDatas[culture].Description = ModInfo.DescriptionID;
{ //foreach (var food in ModInfo.Foods)
food.I18nDatas[culture].Name = food.ID; //{
food.I18nDatas[culture].Description = food.DescriptionID; // food.I18nDatas[culture].Name = food.ID;
} // food.I18nDatas[culture].Description = food.DescriptionID;
foreach (var text in ModInfo.LowTexts) //}
text.I18nDatas[culture].Text = text.ID; //foreach (var text in ModInfo.LowTexts)
foreach (var text in ModInfo.ClickTexts) // text.I18nDatas[culture].Text = text.ID;
text.I18nDatas[culture].Text = text.ID; //foreach (var text in ModInfo.ClickTexts)
foreach (var text in ModInfo.SelectTexts) // text.I18nDatas[culture].Text = text.ID;
{ //foreach (var text in ModInfo.SelectTexts)
text.I18nDatas[culture].Text = text.ID; //{
text.I18nDatas[culture].Choose = text.ChooseID; // text.I18nDatas[culture].Text = text.ID;
} // text.I18nDatas[culture].Choose = text.ChooseID;
foreach (var pet in ModInfo.Pets) //}
{ //foreach (var pet in ModInfo.Pets)
pet.I18nDatas[culture].Name = pet.ID; //{
pet.I18nDatas[culture].PetName = pet.PetNameID; // pet.I18nDatas[culture].Name = pet.ID;
pet.I18nDatas[culture].Description = pet.DescriptionID; // pet.I18nDatas[culture].PetName = pet.PetNameID;
foreach (var work in pet.Works) // pet.I18nDatas[culture].Description = pet.DescriptionID;
work.I18nDatas[culture].Name = work.ID; // foreach (var work in pet.Works)
} // work.I18nDatas[culture].Name = work.ID;
//}
} }
#endregion #endregion
@ -303,7 +303,7 @@ public class ModEditWindowVM : ObservableObjectX
/// <returns>成功为 <see langword="true"/> 失败为 <see langword="false"/></returns> /// <returns>成功为 <see langword="true"/> 失败为 <see langword="false"/></returns>
private bool ValidationData(ModInfoModel model) private bool ValidationData(ModInfoModel model)
{ {
if (I18nHelper.Current.CultureNames.Count == 0) if (ModInfoModel.Current.I18nResource.CultureDatas.HasValue() is false)
{ {
MessageBox.Show( MessageBox.Show(
ModEditWindow, ModEditWindow,

View File

@ -23,7 +23,10 @@ public class PetEditWindowVM : ObservableObjectX
} }
#region Property #region Property
public static I18nHelper I18nData => I18nHelper.Current; /// <summary>
/// I18n资源
/// </summary>
public static I18nResource<string, string> I18nResource => ModInfoModel.Current.I18nResource;
public PetModel? OldPet { get; set; } public PetModel? OldPet { get; set; }
#region Pet #region Pet

View File

@ -11,7 +11,10 @@ namespace VPet.ModMaker.ViewModels.ModEdit.SelectTextEdit;
public class SelectTextEditWindowVM : ObservableObjectX public class SelectTextEditWindowVM : ObservableObjectX
{ {
public static I18nHelper I18nData => I18nHelper.Current; /// <summary>
/// I18n资源
/// </summary>
public static I18nResource<string, string> I18nResource => ModInfoModel.Current.I18nResource;
#region Value #region Value
public SelectTextModel? OldSelectText { get; set; } public SelectTextModel? OldSelectText { get; set; }

View File

@ -92,8 +92,10 @@ public class WorkEditWindowVM : ObservableObjectX
} }
} }
public static ModInfoModel ModInfo => ModInfoModel.Current; /// <summary>
public static I18nHelper I18nData => I18nHelper.Current; /// I18n资源
/// </summary>
public static I18nResource<string, string> I18nResource => ModInfoModel.Current.I18nResource;
#region Property #region Property
public PetModel CurrentPet { get; set; } = null!; public PetModel CurrentPet { get; set; } = null!;
public WorkModel? OldWork { get; set; } public WorkModel? OldWork { get; set; }

View File

@ -230,7 +230,6 @@ public class ModMakerWindowVM : ObservableObjectX
SaveHistories(); SaveHistories();
} }
ModInfoModel.Current?.Close(); ModInfoModel.Current?.Close();
I18nHelper.Current = new();
ModMakerWindow.Show(); ModMakerWindow.Show();
ModMakerWindow.Activate(); ModMakerWindow.Activate();
GC.Collect(); GC.Collect();
@ -305,7 +304,6 @@ public class ModMakerWindowVM : ObservableObjectX
ModEditWindow?.Close(); ModEditWindow?.Close();
ModEditWindow = null!; ModEditWindow = null!;
ModInfoModel.Current?.Close(); ModInfoModel.Current?.Close();
I18nHelper.Current = new();
I18nEditWindow.Current?.Close(true); I18nEditWindow.Current?.Close(true);
ModMakerWindow.Show(); ModMakerWindow.Show();
ModMakerWindow.Activate(); ModMakerWindow.Activate();

View File

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -51,7 +52,11 @@ public partial class AddCultureWindow : WindowX
MessageBox.Show("文化不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning); MessageBox.Show("文化不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return; return;
} }
if (I18nHelper.Current.CultureNames.Contains(ViewModel.Culture)) if (
ModInfoModel.Current.I18nResource.CultureDatas.ContainsKey(
CultureInfo.GetCultureInfo(ViewModel.Culture)
)
)
{ {
MessageBox.Show("此文化已存在".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning); MessageBox.Show("此文化已存在".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return; return;
@ -62,10 +67,8 @@ public partial class AddCultureWindow : WindowX
private void Hyperlink_Click(object? sender, RoutedEventArgs e) private void Hyperlink_Click(object? sender, RoutedEventArgs e)
{ {
Process.Start( NativeUtils.OpenLink(
new ProcessStartInfo( "https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-lcid/a9eac961-e77d-41a6-90a5-ce1a8b0cdb9c"
"https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-lcid/a9eac961-e77d-41a6-90a5-ce1a8b0cdb9c"
)
); );
} }
} }

View File

@ -198,7 +198,7 @@
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!--<Label Content="{ll:Str 动画Id}" /> <!--<Label Content="{ll:Str 动画ID}" />
<TextBox Grid.Column="1" />--> <TextBox Grid.Column="1" />-->
<Label Content="{ll:Str 动画类型}" /> <Label Content="{ll:Str 动画类型}" />
<TextBlock Grid.Column="1" Text="{Binding Anime.GraphType}" /> <TextBlock Grid.Column="1" Text="{Binding Anime.GraphType}" />

View File

@ -45,7 +45,7 @@
Style="{DynamicResource StandardComboBoxStyle}"> Style="{DynamicResource StandardComboBoxStyle}">
<ComboBox.ItemContainerStyle> <ComboBox.ItemContainerStyle>
<Style BasedOn="{StaticResource {x:Type ComboBoxItem}}" TargetType="ComboBoxItem"> <Style BasedOn="{StaticResource {x:Type ComboBoxItem}}" TargetType="ComboBoxItem">
<Setter Property="ToolTip" Value="{Binding CurrentI18nData.Name}" /> <Setter Property="ToolTip" Value="{Binding Name}" />
<Setter Property="Visibility"> <Setter Property="Visibility">
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource AllTrueToCollapsedConverter}"> <MultiBinding Converter="{StaticResource AllTrueToCollapsedConverter}">

View File

@ -58,9 +58,9 @@
</TextBlock> </TextBlock>
<!--<TextBox <!--<TextBox
Grid.Column="1" Grid.Column="1"
pu:TextBoxHelper.Watermark="{ll:Str 动画Id(非必要)}" pu:TextBoxHelper.Watermark="{ll:Str 动画ID(非必要)}"
Text="{Binding Id, UpdateSourceTrigger=PropertyChanged}" />--> Text="{Binding ID, UpdateSourceTrigger=PropertyChanged}" />-->
<!-- pu:TextBoxHelper.Watermark="{ll:Str 动画Id(非必要)}" --> <!-- pu:TextBoxHelper.Watermark="{ll:Str 动画ID(非必要)}" -->
</Grid> </Grid>
</Expander.Header> </Expander.Header>
<Grid> <Grid>
@ -538,7 +538,7 @@
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!--<Label Content="{ll:Str 动画Id}" /> <!--<Label Content="{ll:Str 动画ID}" />
<TextBox Grid.Column="1" />--> <TextBox Grid.Column="1" />-->
<Label Content="{ll:Str 动画类型}" /> <Label Content="{ll:Str 动画类型}" />
<TextBlock Grid.Column="1" Text="{Binding Anime.GraphType}" /> <TextBlock Grid.Column="1" Text="{Binding Anime.GraphType}" />

View File

@ -47,7 +47,7 @@
d:Text="这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本," d:Text="这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,"
pu:TextBoxHelper.Watermark="{ll:Str 文本}" pu:TextBoxHelper.Watermark="{ll:Str 文本}"
Style="{StaticResource TextBox_Wrap}" Style="{StaticResource TextBox_Wrap}"
Text="{Binding ClickText.CurrentI18nData.Text, UpdateSourceTrigger=PropertyChanged}" /> Text="{Binding ClickText.Text, UpdateSourceTrigger=PropertyChanged}" />
</Grid> </Grid>
<Grid Grid.Column="1"> <Grid Grid.Column="1">
<Grid.RowDefinitions> <Grid.RowDefinitions>

View File

@ -38,7 +38,7 @@ public partial class ClickTextEditWindow : Window
private void Button_Yes_Click(object? sender, RoutedEventArgs e) private void Button_Yes_Click(object? sender, RoutedEventArgs e)
{ {
if (string.IsNullOrEmpty(ViewModel.ClickText.ID)) if (string.IsNullOrWhiteSpace(ViewModel.ClickText.ID))
{ {
MessageBox.Show("ID不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning); MessageBox.Show("ID不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return; return;
@ -51,7 +51,7 @@ public partial class ClickTextEditWindow : Window
MessageBox.Show("此ID已存在".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning); MessageBox.Show("此ID已存在".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return; return;
} }
if (string.IsNullOrEmpty(ViewModel.ClickText.CurrentI18nData.Text)) if (string.IsNullOrWhiteSpace(ViewModel.ClickText.Text))
{ {
MessageBox.Show("文本不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning); MessageBox.Show("文本不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return; return;

View File

@ -19,7 +19,7 @@
<RowDefinition /> <RowDefinition />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<TextBox <TextBox
pu:TextBoxHelper.Watermark="{ll:Str 搜索Id}" pu:TextBoxHelper.Watermark="{ll:Str 搜索ID}"
Style="{DynamicResource StandardTextBoxStyle}" Style="{DynamicResource StandardTextBoxStyle}"
Text="{Binding Search, UpdateSourceTrigger=PropertyChanged}" /> Text="{Binding Search, UpdateSourceTrigger=PropertyChanged}" />
<DataGrid <DataGrid
@ -53,12 +53,12 @@
SortMemberPath="ID" /> SortMemberPath="ID" />
<DataGridTextColumn <DataGridTextColumn
MaxWidth="300" MaxWidth="300"
Binding="{Binding CurrentI18nData.Text}" Binding="{Binding Text}"
CanUserSort="True" CanUserSort="True"
ElementStyle="{StaticResource TextBlock_Wrap}" ElementStyle="{StaticResource TextBlock_Wrap}"
Header="{ll:Str 文本}" Header="{ll:Str 文本}"
IsReadOnly="True" IsReadOnly="True"
SortMemberPath="CurrentI18nData.Text" /> SortMemberPath="Text" />
<DataGridTextColumn <DataGridTextColumn
Binding="{Binding Mode.Value}" Binding="{Binding Mode.Value}"
CanUserSort="True" CanUserSort="True"

View File

@ -59,7 +59,7 @@
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition /> <RowDefinition />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Label Content="Id" /> <Label Content="ID" />
<TextBox <TextBox
Grid.Column="1" Grid.Column="1"
pu:TextBoxHelper.Watermark="ID" pu:TextBoxHelper.Watermark="ID"
@ -82,14 +82,14 @@
Grid.Row="3" Grid.Row="3"
Grid.Column="1" Grid.Column="1"
pu:TextBoxHelper.Watermark="{ll:Str 食物名称}" pu:TextBoxHelper.Watermark="{ll:Str 食物名称}"
Text="{Binding Food.CurrentI18nData.Name, UpdateSourceTrigger=PropertyChanged}" /> Text="{Binding Food.Name, UpdateSourceTrigger=PropertyChanged}" />
<Label Grid.Row="4" Content="{ll:Str 食物描述}" /> <Label Grid.Row="4" Content="{ll:Str 食物描述}" />
<TextBox <TextBox
Grid.Row="4" Grid.Row="4"
Grid.Column="1" Grid.Column="1"
pu:TextBoxHelper.Watermark="{ll:Str 食物描述}" pu:TextBoxHelper.Watermark="{ll:Str 食物描述}"
Style="{StaticResource TextBox_Wrap}" Style="{StaticResource TextBox_Wrap}"
Text="{Binding Food.CurrentI18nData.Description, UpdateSourceTrigger=PropertyChanged}" /> Text="{Binding Food.Description, UpdateSourceTrigger=PropertyChanged}" />
</Grid> </Grid>
</ScrollViewer> </ScrollViewer>
</Grid> </Grid>

View File

@ -74,12 +74,12 @@
</DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn> </DataGridTemplateColumn>
<DataGridTextColumn <DataGridTextColumn
Binding="{Binding CurrentI18nData.Name}" Binding="{Binding Name}"
CanUserSort="True" CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}" ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 食物名称}" Header="{ll:Str 食物名称}"
IsReadOnly="True" IsReadOnly="True"
SortMemberPath="CurrentI18nData.Name" /> SortMemberPath="Name" />
<DataGridTextColumn <DataGridTextColumn
Binding="{Binding Type}" Binding="{Binding Type}"
CanUserSort="True" CanUserSort="True"
@ -152,12 +152,12 @@
SortMemberPath="Price" /> SortMemberPath="Price" />
<DataGridTextColumn <DataGridTextColumn
MaxWidth="300" MaxWidth="300"
Binding="{Binding CurrentI18nData.Description}" Binding="{Binding Description}"
CanUserSort="True" CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_Wrap}" ElementStyle="{DynamicResource TextBlock_Wrap}"
Header="{ll:Str 描述}" Header="{ll:Str 描述}"
IsReadOnly="True" IsReadOnly="True"
SortMemberPath="CurrentI18nData.Description" /> SortMemberPath="Description" />
</DataGrid.Columns> </DataGrid.Columns>
</DataGrid> </DataGrid>
<Button <Button

View File

@ -6,6 +6,7 @@ using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Data; using System.Windows.Data;
using HKW.HKWUtils.Extensions;
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using Panuon.WPF.UI; using Panuon.WPF.UI;
using VPet.ModMaker.Models; using VPet.ModMaker.Models;
@ -89,10 +90,7 @@ public partial class I18nEditWindow : WindowX
/// <param name="culture"></param> /// <param name="culture"></param>
public void AddCulture(string culture) public void AddCulture(string culture)
{ {
var dataPath = string.Format( var dataPath = string.Format(ValueBindingFormat, culture);
ValueBindingFormat,
I18nHelper.Current.CultureNames.IndexOf(culture)
);
// 文化数据列 // 文化数据列
var column = new DataGridTextColumn() var column = new DataGridTextColumn()
{ {
@ -118,8 +116,7 @@ public partial class I18nEditWindow : WindowX
_dataGridI18nColumns.Remove(culture); _dataGridI18nColumns.Remove(culture);
foreach (var columnData in _dataGridI18nColumns) foreach (var columnData in _dataGridI18nColumns)
{ {
var index = I18nHelper.Current.CultureNames.IndexOf(columnData.Key); var dataPath = string.Format(ValueBindingFormat, culture);
var dataPath = string.Format(ValueBindingFormat, index);
columnData.Value.Binding = new Binding(dataPath) { Mode = BindingMode.TwoWay }; columnData.Value.Binding = new Binding(dataPath) { Mode = BindingMode.TwoWay };
columnData.Value.SortMemberPath = dataPath; columnData.Value.SortMemberPath = dataPath;
} }

View File

@ -45,7 +45,7 @@
d:Text="这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本," d:Text="这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,"
pu:TextBoxHelper.Watermark="{ll:Str 文本}" pu:TextBoxHelper.Watermark="{ll:Str 文本}"
Style="{StaticResource TextBox_Wrap}" Style="{StaticResource TextBox_Wrap}"
Text="{Binding LowText.CurrentI18nData.Text, UpdateSourceTrigger=PropertyChanged}" /> Text="{Binding LowText.Text, UpdateSourceTrigger=PropertyChanged}" />
</Grid> </Grid>
<Grid Grid.Column="1"> <Grid Grid.Column="1">
<Grid.RowDefinitions> <Grid.RowDefinitions>

View File

@ -39,7 +39,7 @@ public partial class LowTextEditWindow : Window
private void Button_Yes_Click(object? sender, RoutedEventArgs e) private void Button_Yes_Click(object? sender, RoutedEventArgs e)
{ {
if (string.IsNullOrEmpty(ViewModel.LowText.ID)) if (string.IsNullOrWhiteSpace(ViewModel.LowText.ID))
{ {
MessageBox.Show("ID不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning); MessageBox.Show("ID不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return; return;
@ -52,7 +52,7 @@ public partial class LowTextEditWindow : Window
MessageBox.Show("此ID已存在".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning); MessageBox.Show("此ID已存在".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return; return;
} }
if (string.IsNullOrEmpty(ViewModel.LowText.CurrentI18nData.Text)) if (string.IsNullOrWhiteSpace(ViewModel.LowText.Text))
{ {
MessageBox.Show("文本不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning); MessageBox.Show("文本不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return; return;

View File

@ -54,12 +54,12 @@
SortMemberPath="ID" /> SortMemberPath="ID" />
<DataGridTextColumn <DataGridTextColumn
MaxWidth="300" MaxWidth="300"
Binding="{Binding CurrentI18nData.Text}" Binding="{Binding Text}"
CanUserSort="True" CanUserSort="True"
ElementStyle="{StaticResource TextBlock_Wrap}" ElementStyle="{StaticResource TextBlock_Wrap}"
Header="{ll:Str 文本}" Header="{ll:Str 文本}"
IsReadOnly="True" IsReadOnly="True"
SortMemberPath="CurrentI18nData.Text" /> SortMemberPath="Text" />
<DataGridTextColumn <DataGridTextColumn
Binding="{Binding Mode}" Binding="{Binding Mode}"
CanUserSort="True" CanUserSort="True"

View File

@ -119,7 +119,7 @@
Grid.Row="4" Grid.Row="4"
Grid.Column="1" Grid.Column="1"
pu:TextBoxHelper.Watermark="{ll:Str 模组名称}" pu:TextBoxHelper.Watermark="{ll:Str 模组名称}"
Text="{Binding ModInfo.CurrentI18nData.Name, UpdateSourceTrigger=PropertyChanged}" /> Text="{Binding ModInfo.Name, UpdateSourceTrigger=PropertyChanged}" />
<Label Grid.Row="5" Content="{ll:Str 模组介绍}" /> <Label Grid.Row="5" Content="{ll:Str 模组介绍}" />
<TextBox <TextBox
x:Name="TextBox_Description" x:Name="TextBox_Description"
@ -129,7 +129,7 @@
VerticalContentAlignment="Top" VerticalContentAlignment="Top"
d:Text="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" d:Text="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
pu:TextBoxHelper.Watermark="{ll:Str 模组介绍}" pu:TextBoxHelper.Watermark="{ll:Str 模组介绍}"
Text="{Binding ModInfo.CurrentI18nData.Description, UpdateSourceTrigger=PropertyChanged}" Text="{Binding ModInfo.Description, UpdateSourceTrigger=PropertyChanged}"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
</Grid> </Grid>
</ScrollViewer> </ScrollViewer>
@ -279,9 +279,9 @@
x:Name="ListBox_Cultures" x:Name="ListBox_Cultures"
Grid.Row="1" Grid.Row="1"
d:ItemsSource="{d:SampleData ItemCount=5}" d:ItemsSource="{d:SampleData ItemCount=5}"
ItemsSource="{Binding I18nData.CultureNames}" ItemsSource="{Binding I18nResource.CultureDatas.ObservableKeys}"
ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto"
SelectedItem="{Binding I18nData.CultureName}"> SelectedItem="{Binding I18nResource.CurrentCulture}">
<ListBox.ItemContainerStyle> <ListBox.ItemContainerStyle>
<Style BasedOn="{StaticResource {x:Type ListBoxItem}}" TargetType="ListBoxItem"> <Style BasedOn="{StaticResource {x:Type ListBoxItem}}" TargetType="ListBoxItem">
<Setter Property="Tag" Value="{Binding DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" /> <Setter Property="Tag" Value="{Binding DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" />

View File

@ -16,6 +16,7 @@ using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using System.Windows.Shapes; using System.Windows.Shapes;
using HKW.HKWUtils.Extensions;
using LinePutScript.Localization.WPF; using LinePutScript.Localization.WPF;
using Microsoft.Win32; using Microsoft.Win32;
using Panuon.WPF; using Panuon.WPF;
@ -72,7 +73,7 @@ public partial class ModEditWindow : WindowX
/// </summary> /// </summary>
public void InitializeData() public void InitializeData()
{ {
if (I18nHelper.Current.CultureNames.Count == 0) if (ModInfoModel.Current.I18nResource.CultureDatas.HasValue() is false)
{ {
if ( if (
MessageBox.Show("未添加任何文化,确定要添加文化吗?".Translate(), "", MessageBoxButton.YesNo) MessageBox.Show("未添加任何文化,确定要添加文化吗?".Translate(), "", MessageBoxButton.YesNo)
@ -81,16 +82,20 @@ public partial class ModEditWindow : WindowX
return; return;
ViewModel.AddCultureCommand_ExecuteCommand(); ViewModel.AddCultureCommand_ExecuteCommand();
if ( if (
I18nHelper.Current.CultureNames.Count == 0 ModInfoModel.Current.I18nResource.CultureDatas.HasValue() is false
|| MessageBox.Show( || MessageBox.Show(
"需要将文化 {0} 设为主要文化吗?".Translate(I18nHelper.Current.CultureNames.First()), "需要将文化 {0} 设为主要文化吗?".Translate(
ModInfoModel.Current.I18nResource.CultureDatas.First().Key.Name
),
"", "",
MessageBoxButton.YesNo MessageBoxButton.YesNo
) )
is not MessageBoxResult.Yes is not MessageBoxResult.Yes
) )
return; return;
ViewModel.SetMainCultureCommand_ExecuteCommand(I18nHelper.Current.CultureNames.First()); ViewModel.SetMainCultureCommand_ExecuteCommand(
ModInfoModel.Current.I18nResource.CultureDatas.First().Key.Name
);
} }
} }

View File

@ -76,7 +76,7 @@
<TextBox <TextBox
Grid.Row="3" Grid.Row="3"
Grid.Column="1" Grid.Column="1"
Text="{Binding Pet.CurrentI18nData.Description}" />--> Text="{Binding Pet.Description}" />-->
</Grid> </Grid>
</Grid> </Grid>
<Grid Grid.Column="1"> <Grid Grid.Column="1">

View File

@ -45,7 +45,7 @@
Style="{DynamicResource StandardComboBoxStyle}"> Style="{DynamicResource StandardComboBoxStyle}">
<ComboBox.ItemContainerStyle> <ComboBox.ItemContainerStyle>
<Style BasedOn="{StaticResource {x:Type ComboBoxItem}}" TargetType="ComboBoxItem"> <Style BasedOn="{StaticResource {x:Type ComboBoxItem}}" TargetType="ComboBoxItem">
<Setter Property="ToolTip" Value="{Binding CurrentI18nData.Name}" /> <Setter Property="ToolTip" Value="{Binding Name}" />
<Setter Property="Visibility"> <Setter Property="Visibility">
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource AllTrueToCollapsedConverter}"> <MultiBinding Converter="{StaticResource AllTrueToCollapsedConverter}">

View File

@ -368,26 +368,26 @@
Grid.Row="1" Grid.Row="1"
Grid.Column="1" Grid.Column="1"
pu:TextBoxHelper.Watermark="{ll:Str 名称}" pu:TextBoxHelper.Watermark="{ll:Str 名称}"
Text="{Binding Pet.CurrentI18nData.Name, UpdateSourceTrigger=PropertyChanged}" />--> Text="{Binding Pet.Name, UpdateSourceTrigger=PropertyChanged}" />-->
<Label Grid.Row="2" Content="{ll:Str 名称}" /> <Label Grid.Row="2" Content="{ll:Str 名称}" />
<TextBox <TextBox
Grid.Row="2" Grid.Row="2"
Grid.Column="1" Grid.Column="1"
pu:TextBoxHelper.Watermark="{ll:Str 名称}" pu:TextBoxHelper.Watermark="{ll:Str 名称}"
Text="{Binding Pet.CurrentI18nData.Name, UpdateSourceTrigger=PropertyChanged}" /> Text="{Binding Pet.Name, UpdateSourceTrigger=PropertyChanged}" />
<Label Grid.Row="3" Content="{ll:Str 宠物名称}" /> <Label Grid.Row="3" Content="{ll:Str 宠物名称}" />
<TextBox <TextBox
Grid.Row="3" Grid.Row="3"
Grid.Column="1" Grid.Column="1"
pu:TextBoxHelper.Watermark="{ll:Str 宠物名称}" pu:TextBoxHelper.Watermark="{ll:Str 宠物名称}"
Text="{Binding Pet.CurrentI18nData.PetName, UpdateSourceTrigger=PropertyChanged}" /> Text="{Binding Pet.PetName, UpdateSourceTrigger=PropertyChanged}" />
<Label Grid.Row="4" Content="{ll:Str 描述}" /> <Label Grid.Row="4" Content="{ll:Str 描述}" />
<TextBox <TextBox
Grid.Row="4" Grid.Row="4"
Grid.Column="1" Grid.Column="1"
pu:TextBoxHelper.Watermark="{ll:Str 描述}" pu:TextBoxHelper.Watermark="{ll:Str 描述}"
Style="{StaticResource TextBox_Wrap}" Style="{StaticResource TextBox_Wrap}"
Text="{Binding Pet.CurrentI18nData.Description, UpdateSourceTrigger=PropertyChanged}" /> Text="{Binding Pet.Description, UpdateSourceTrigger=PropertyChanged}" />
</Grid> </Grid>
</Grid> </Grid>
<Grid Grid.Column="1"> <Grid Grid.Column="1">

View File

@ -49,15 +49,15 @@ public partial class PetEditWindow : Window
{ {
if (string.IsNullOrWhiteSpace(ViewModel.Pet.ID)) if (string.IsNullOrWhiteSpace(ViewModel.Pet.ID))
{ {
MessageBox.Show("Id不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning); MessageBox.Show("ID不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return; return;
} }
if (string.IsNullOrWhiteSpace(ViewModel.Pet.CurrentI18nData.Name)) if (string.IsNullOrWhiteSpace(ViewModel.Pet.Name))
{ {
MessageBox.Show("名称不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning); MessageBox.Show("名称不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return; return;
} }
if (string.IsNullOrWhiteSpace(ViewModel.Pet.CurrentI18nData.PetName)) if (string.IsNullOrWhiteSpace(ViewModel.Pet.PetName))
{ {
MessageBox.Show( MessageBox.Show(
"宠物名称不可为空".Translate(), "宠物名称不可为空".Translate(),
@ -72,7 +72,7 @@ public partial class PetEditWindow : Window
&& ModInfoModel.Current.Pets.Any(i => i.ID == ViewModel.Pet.ID) && ModInfoModel.Current.Pets.Any(i => i.ID == ViewModel.Pet.ID)
) )
{ {
MessageBox.Show("此Id已存在", "", MessageBoxButton.OK, MessageBoxImage.Warning); MessageBox.Show("此ID已存在", "", MessageBoxButton.OK, MessageBoxImage.Warning);
return; return;
} }
IsCancel = false; IsCancel = false;

View File

@ -82,19 +82,19 @@
</DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn> </DataGridTemplateColumn>
<DataGridTextColumn <DataGridTextColumn
Binding="{Binding CurrentI18nData.Name}" Binding="{Binding Name}"
CanUserSort="True" CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}" ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 名称}" Header="{ll:Str 名称}"
IsReadOnly="True" IsReadOnly="True"
SortMemberPath="CurrentI18nData.Name" /> SortMemberPath="Name" />
<DataGridTextColumn <DataGridTextColumn
Binding="{Binding CurrentI18nData.PetName}" Binding="{Binding PetName}"
CanUserSort="True" CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}" ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 宠物名称}" Header="{ll:Str 宠物名称}"
IsReadOnly="True" IsReadOnly="True"
SortMemberPath="CurrentI18nData.Name" /> SortMemberPath="Name" />
<DataGridTextColumn <DataGridTextColumn
Binding="{Binding Tags}" Binding="{Binding Tags}"
CanUserSort="True" CanUserSort="True"
@ -103,12 +103,12 @@
IsReadOnly="True" IsReadOnly="True"
SortMemberPath="Tags" /> SortMemberPath="Tags" />
<DataGridTextColumn <DataGridTextColumn
Binding="{Binding CurrentI18nData.Description}" Binding="{Binding Description}"
CanUserSort="True" CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}" ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 描述}" Header="{ll:Str 描述}"
IsReadOnly="True" IsReadOnly="True"
SortMemberPath="CurrentI18nData.Description" /> SortMemberPath="Description" />
</DataGrid.Columns> </DataGrid.Columns>
</DataGrid> </DataGrid>
<Button <Button

View File

@ -50,7 +50,7 @@
Grid.Column="1" Grid.Column="1"
pu:TextBoxHelper.Watermark="{ll:Str 显示在选项列表中的名称}" pu:TextBoxHelper.Watermark="{ll:Str 显示在选项列表中的名称}"
Style="{StaticResource TextBox_Wrap}" Style="{StaticResource TextBox_Wrap}"
Text="{Binding SelectText.CurrentI18nData.Choose, UpdateSourceTrigger=PropertyChanged}" Text="{Binding SelectText.Choose, UpdateSourceTrigger=PropertyChanged}"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
</Grid> </Grid>
<TextBox <TextBox
@ -59,7 +59,7 @@
d:Text="这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本," d:Text="这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,这是一个测试文本,"
pu:TextBoxHelper.Watermark="{ll:Str 文本}" pu:TextBoxHelper.Watermark="{ll:Str 文本}"
Style="{StaticResource TextBox_Wrap}" Style="{StaticResource TextBox_Wrap}"
Text="{Binding SelectText.CurrentI18nData.Text, UpdateSourceTrigger=PropertyChanged}" /> Text="{Binding SelectText.Text, UpdateSourceTrigger=PropertyChanged}" />
</Grid> </Grid>
<Grid Grid.Column="1"> <Grid Grid.Column="1">
<Grid.RowDefinitions> <Grid.RowDefinitions>

View File

@ -48,7 +48,7 @@ public partial class SelectTextEditWindow : Window
{ {
if (string.IsNullOrWhiteSpace(ViewModel.SelectText.ID)) if (string.IsNullOrWhiteSpace(ViewModel.SelectText.ID))
{ {
MessageBox.Show("Id不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning); MessageBox.Show("ID不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return; return;
} }
if ( if (
@ -56,10 +56,10 @@ public partial class SelectTextEditWindow : Window
&& ModInfoModel.Current.SelectTexts.Any(i => i.ID == ViewModel.SelectText.ID) && ModInfoModel.Current.SelectTexts.Any(i => i.ID == ViewModel.SelectText.ID)
) )
{ {
MessageBox.Show("此Id已存在".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning); MessageBox.Show("此ID已存在".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return; return;
} }
if (string.IsNullOrWhiteSpace(ViewModel.SelectText.CurrentI18nData.Choose)) if (string.IsNullOrWhiteSpace(ViewModel.SelectText.Choose))
{ {
MessageBox.Show( MessageBox.Show(
"选项名不可为空".Translate(), "选项名不可为空".Translate(),
@ -69,7 +69,7 @@ public partial class SelectTextEditWindow : Window
); );
return; return;
} }
if (string.IsNullOrWhiteSpace(ViewModel.SelectText.CurrentI18nData.Text)) if (string.IsNullOrWhiteSpace(ViewModel.SelectText.Text))
{ {
MessageBox.Show("文本不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning); MessageBox.Show("文本不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return; return;

View File

@ -53,20 +53,20 @@
SortMemberPath="ID" /> SortMemberPath="ID" />
<DataGridTextColumn <DataGridTextColumn
MaxWidth="300" MaxWidth="300"
Binding="{Binding CurrentI18nData.Text}" Binding="{Binding Text}"
CanUserSort="True" CanUserSort="True"
ElementStyle="{StaticResource TextBlock_Wrap}" ElementStyle="{StaticResource TextBlock_Wrap}"
Header="{ll:Str 文本}" Header="{ll:Str 文本}"
IsReadOnly="True" IsReadOnly="True"
SortMemberPath="CurrentI18nData.Text" /> SortMemberPath="Text" />
<DataGridTextColumn <DataGridTextColumn
MaxWidth="200" MaxWidth="200"
Binding="{Binding CurrentI18nData.Choose}" Binding="{Binding Choose}"
CanUserSort="True" CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}" ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 选择名}" Header="{ll:Str 选择名}"
IsReadOnly="True" IsReadOnly="True"
SortMemberPath="CurrentI18nData.Choose" /> SortMemberPath="Choose" />
<DataGridTextColumn <DataGridTextColumn
MaxWidth="200" MaxWidth="200"
Binding="{Binding Tags}" Binding="{Binding Tags}"

View File

@ -132,7 +132,7 @@
<TextBox <TextBox
Grid.Row="1" Grid.Row="1"
Grid.Column="1" Grid.Column="1"
Text="{Binding Work.CurrentI18nData.Name}" /> Text="{Binding Work.Name}" />
<Label Grid.Row="2" Content="{ll:Str 类型}" /> <Label Grid.Row="2" Content="{ll:Str 类型}" />
<ComboBox <ComboBox
Grid.Row="2" Grid.Row="2"
@ -163,7 +163,7 @@
<TextBox <TextBox
Grid.Row="3" Grid.Row="3"
Grid.Column="1" Grid.Column="1"
Text="{Binding Pet.CurrentI18nData.Description}" />--> Text="{Binding Pet.Description}" />-->
</Grid> </Grid>
</Grid> </Grid>
<Grid Grid.Column="1"> <Grid Grid.Column="1">

View File

@ -48,7 +48,7 @@
Style="{DynamicResource StandardComboBoxStyle}"> Style="{DynamicResource StandardComboBoxStyle}">
<ComboBox.ItemContainerStyle> <ComboBox.ItemContainerStyle>
<Style BasedOn="{StaticResource {x:Type ComboBoxItem}}" TargetType="ComboBoxItem"> <Style BasedOn="{StaticResource {x:Type ComboBoxItem}}" TargetType="ComboBoxItem">
<Setter Property="ToolTip" Value="{Binding CurrentI18nData.Name}" /> <Setter Property="ToolTip" Value="{Binding Name}" />
<Setter Property="Visibility"> <Setter Property="Visibility">
<Setter.Value> <Setter.Value>
<MultiBinding Converter="{StaticResource AllTrueToCollapsedConverter}"> <MultiBinding Converter="{StaticResource AllTrueToCollapsedConverter}">
@ -111,12 +111,12 @@
IsReadOnly="True" IsReadOnly="True"
SortMemberPath="ID" /> SortMemberPath="ID" />
<DataGridTextColumn <DataGridTextColumn
Binding="{Binding CurrentI18nData.Name}" Binding="{Binding Name}"
CanUserSort="True" CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}" ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 工作名称}" Header="{ll:Str 工作名称}"
IsReadOnly="True" IsReadOnly="True"
SortMemberPath="CurrentI18nData.Name" /> SortMemberPath="Name" />
<DataGridTextColumn <DataGridTextColumn
Binding="{Binding WorkType}" Binding="{Binding WorkType}"
CanUserSort="True" CanUserSort="True"