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

View File

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

View File

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

View File

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

View File

@ -17,9 +17,14 @@ namespace VPet.ModMaker.Models;
/// <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)
: this()
@ -37,9 +42,6 @@ public class ClickTextModel : I18nModel<I18nClickTextModel>
Drink = clickText.Drink.Clone();
Feel = clickText.Feel.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)
@ -121,6 +123,15 @@ public class ClickTextModel : I18nModel<I18nClickTextModel>
}
#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
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _working = string.Empty;

View File

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

View File

@ -21,11 +21,21 @@ namespace VPet.ModMaker.Models;
/// <summary>
/// 食物模型
/// </summary>
public class FoodModel : I18nModel<I18nFoodModel>
public class FoodModel : ObservableObjectX
{
public FoodModel()
{
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(
@ -54,9 +64,6 @@ public class FoodModel : I18nModel<I18nFoodModel>
{
model.Adapt(this);
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)
@ -108,6 +115,26 @@ public class FoodModel : I18nModel<I18nFoodModel>
}
#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
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _graph = string.Empty;
@ -310,7 +337,7 @@ public class FoodModel : I18nModel<I18nFoodModel>
//};
}
public void RefreshId()
public void RefreshID()
{
DescriptionID = $"{ID}_{nameof(DescriptionID)}";
}
@ -318,34 +345,10 @@ public class FoodModel : I18nModel<I18nFoodModel>
public void Close()
{
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>
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)
: 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)
@ -69,6 +70,15 @@ public class LowTextModel : I18nModel<I18nLowTextModel>
}
#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
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private LowText.ModeType _mode;
@ -119,24 +129,3 @@ public class LowTextModel : I18nModel<I18nLowTextModel>
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.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
@ -26,10 +27,11 @@ namespace VPet.ModMaker.Models;
/// <summary>
/// 模组信息模型
/// </summary>
public class ModInfoModel : I18nModel<I18nModInfoModel>
public class ModInfoModel : ObservableObjectX
{
public ModInfoModel()
{
Current = this;
PropertyChanged += ModInfoModel_PropertyChanged;
Pets.CollectionChanged += Pets_CollectionChanged;
}
@ -104,25 +106,22 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
LoadAnime(petModel, p);
}
//loader.Pets.First().Name = "TestMainPet";
//Pets.Insert(0, new(loader.Pets.First(), true));
// 插入本体宠物
foreach (var pet in ModMakerInfo.MainPets)
{
// 确保Id不重复
// 确保ID不重复
if (Pets.All(i => i.ID != pet.Key))
Pets.Insert(0, pet.Value);
}
// 载入本地化
foreach (var lang in loader.I18nDatas)
I18nDatas.Add(lang.Key, lang.Value);
OtherI18nDatas = loader.OtherI18nDatas;
// 载入本地化模组信息
//foreach (var lang in loader.I18nDatas)
// I18nDatas.Add(lang.Key, lang.Value);
//OtherI18nDatas = loader.I18nDatas;
LoadI18nDatas();
RefreshAllId();
if (I18nHelper.Current.CultureNames.HasValue())
LoadI18nDatas(loader);
RefreshAllID();
if (I18nResource.CultureDatas.HasValue())
RefreshID();
}
@ -143,6 +142,21 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
/// </summary>
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
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private bool _autoSetFoodPrice;
@ -173,12 +187,12 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
#region ModInfo
/// <summary>
/// 作者Id
/// 作者ID
/// </summary>
public long AuthorID { get; }
/// <summary>
/// 项目Id
/// 项目ID
/// </summary>
public ulong ItemID { get; }
@ -187,7 +201,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
private string _id = string.Empty;
/// <summary>
/// Id
/// ID
/// </summary>
public string ID
{
@ -198,15 +212,15 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
#region DescriptionID
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _descriptionId = string.Empty;
private string _descriptionID = string.Empty;
/// <summary>
/// 描述Id
/// 描述ID
/// </summary>
public string DescriptionID
{
get => _descriptionId;
set => SetProperty(ref _descriptionId, value);
get => _descriptionID;
set => SetProperty(ref _descriptionID, value);
}
#endregion
@ -322,15 +336,6 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
}
#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
private void Pets_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
@ -439,100 +444,121 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
/// <summary>
/// 加载本地化数据
/// </summary>
private void LoadI18nDatas()
private void LoadI18nDatas(ModLoader modLoader)
{
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)
if (modLoader.I18nDatas.HasValue() is false)
return;
I18nHelper.Current.CultureName = I18nHelper.Current.CultureNames.First();
foreach (var i18nData in OtherI18nDatas)
foreach (var cultureDatas in modLoader.I18nDatas)
{
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);
var culture = CultureInfo.GetCultureInfo(cultureDatas.Key);
I18nResource.AddCulture(culture);
foreach (var data in cultureDatas.Value)
I18nResource.AddCultureData(culture, data.Key, data.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)
{
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();
food.RefreshID();
foreach (var selectText in SelectTexts)
selectText.RefreshID();
foreach (var pet in Pets)
@ -554,7 +580,6 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
/// <param name="path">路径</param>
public void SaveTo(string path)
{
SaveI18nDatas.Clear();
// 保存模型信息
SaveModInfo(path);
// 保存模组数据
@ -563,7 +588,6 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
SaveText(path);
SaveI18nData(path);
SaveImage(path);
SaveI18nDatas.Clear();
}
/// <summary>
@ -576,10 +600,6 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
if (File.Exists(modInfoFile) is false)
File.Create(modInfoFile).Close();
SaveI18nDatas.Clear();
foreach (var cultureName in I18nHelper.Current.CultureNames)
SaveI18nDatas.Add(cultureName, new());
var lps = new LPS()
{
new Line("vupmod", ID)
@ -593,13 +613,23 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
new Line("itemid", ItemID.ToString()),
new Line("cachedate", DateTime.Now.Date.ToString("s"))
};
foreach (var cultureName in I18nHelper.Current.CultureNames)
foreach (var cultureData in Current.I18nResource.CultureDatas)
{
lps.Add(
new Line("lang", cultureName)
new Line("cultureDatas", cultureData.Key.Name)
{
new Sub(ID, I18nDatas[cultureName].Name),
new Sub(DescriptionID, I18nDatas[cultureName].Description),
new Sub(
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();
var lps = new LPS();
foreach (var food in Foods)
{
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());
}
@ -690,15 +712,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
File.Create(textFile).Close();
var lps = new LPS();
foreach (var text in SelectTexts)
{
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());
}
@ -714,13 +728,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
File.Create(textFile).Close();
var lps = new LPS();
foreach (var text in LowTexts)
{
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());
}
@ -736,32 +744,26 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
File.Create(textFile).Close();
var lps = new LPS();
foreach (var text in ClickTexts)
{
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());
}
#endregion
/// <summary>
/// 保存I18n数据
/// 保存I18n资源
/// </summary>
/// <param name="path">路径</param>
private void SaveI18nData(string path)
{
var langPath = Path.Combine(path, "lang");
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);
var cultureFile = Path.Combine(culturePath, $"{cultureName}.lps");
var cultureFile = Path.Combine(culturePath, $"{cultureData.Key.Name}.lps");
File.Create(cultureFile).Close();
var lps = new LPS();
foreach (var data in SaveI18nDatas[cultureName])
foreach (var data in cultureData.Value)
lps.Add(new Line(data.Key, data.Value));
File.WriteAllText(cultureFile, lps.ToString());
}
@ -806,7 +808,7 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
// 保存模型信息
SaveModInfo(path);
// 保存文化数据
var langPath = Path.Combine(path, "lang");
var langPath = Path.Combine(path, "cultureDatas");
Directory.CreateDirectory(langPath);
foreach (var cultureName in cultures)
{
@ -828,26 +830,26 @@ public class ModInfoModel : I18nModel<I18nModInfoModel>
}
}
public class I18nModInfoModel : ObservableObjectX
{
#region Name
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _name = string.Empty;
//public class I18nModInfoModel : ObservableObjectX
//{
// #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 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 string Description
// {
// get => _description;
// set => SetProperty(ref _description, value);
// }
// #endregion
//}

View File

@ -23,13 +23,24 @@ namespace VPet.ModMaker.Models;
/// <summary>
/// 宠物模型
/// </summary>
public class PetModel : I18nModel<I18nPetInfoModel>
public class PetModel : ObservableObjectX
{
public PetModel()
{
PropertyChanged += PetModel_PropertyChanged;
Animes.PropertyChanged += Animes_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)
@ -54,10 +65,6 @@ public class PetModel : I18nModel<I18nPetInfoModel>
RaisePoint = model.RaisePoint.Clone();
foreach (var work in model.Works)
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)
@ -185,6 +192,37 @@ public class PetModel : I18nModel<I18nPetInfoModel>
}
#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
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _tags = string.Empty;
@ -344,16 +382,17 @@ public class PetModel : I18nModel<I18nPetInfoModel>
/// <param name="path">路径</param>
public void Save(string path)
{
foreach (var cultureName in I18nHelper.Current.CultureNames)
{
ModInfoModel.SaveI18nDatas[cultureName].TryAdd(ID, I18nDatas[cultureName].Name);
ModInfoModel
.SaveI18nDatas[cultureName]
.TryAdd(PetNameID, I18nDatas[cultureName].PetName);
ModInfoModel
.SaveI18nDatas[cultureName]
.TryAdd(DescriptionID, I18nDatas[cultureName].Description);
}
// TODO
//foreach (var cultureName in I18nHelper.Current.CultureNames)
//{
// ModInfoModel.SaveI18nDatas[cultureName].TryAdd(ID, I18nDatas[cultureName].Name);
// ModInfoModel
// .SaveI18nDatas[cultureName]
// .TryAdd(PetNameID, I18nDatas[cultureName].PetName);
// ModInfoModel
// .SaveI18nDatas[cultureName]
// .TryAdd(DescriptionID, I18nDatas[cultureName].Description);
//}
var petFile = Path.Combine(path, $"{ID}.lps");
if (File.Exists(petFile) is false)
File.Create(petFile).Close();
@ -400,13 +439,14 @@ public class PetModel : I18nModel<I18nPetInfoModel>
{
foreach (var work in Works)
{
lps.Add(LPSConvert.SerializeObjectToLine<Line>(work.ToWork(), "work"));
foreach (var cultureName in I18nHelper.Current.CultureNames)
{
ModInfoModel
.SaveI18nDatas[cultureName]
.TryAdd(work.ID, work.I18nDatas[cultureName].Name);
}
//TODO
//lps.Add(LPSConvert.SerializeObjectToLine<Line>(work.ToWork(), "work"));
//foreach (var cultureName in I18nHelper.Current.CultureNames)
//{
// ModInfoModel
// .SaveI18nDatas[cultureName]
// .TryAdd(work.ID, work.I18nDatas[cultureName].Name);
//}
}
}
@ -545,51 +585,6 @@ public class PetModel : I18nModel<I18nPetInfoModel>
#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
: ObservableObjectX,
IEquatable<ObservableMultiStateRectangleLocation>,

View File

@ -16,9 +16,21 @@ namespace VPet.ModMaker.Models;
/// <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)
: this()
@ -37,10 +49,6 @@ public class SelectTextModel : I18nModel<I18nSelectTextModel>
Drink = model.Drink.Clone();
Feel = model.Feel.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)
@ -126,6 +134,26 @@ public class SelectTextModel : I18nModel<I18nSelectTextModel>
}
#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>
@ -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>
public class WorkModel : I18nModel<I18nWorkModel>
public class WorkModel : ObservableObjectX
{
public WorkModel()
{
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(
@ -71,9 +74,6 @@ public class WorkModel : I18nModel<I18nWorkModel>
Width = model.Width;
//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)
@ -111,12 +111,12 @@ public class WorkModel : I18nModel<I18nWorkModel>
public static FrozenSet<VPet_Simulator.Core.GraphHelper.Work.WorkType> WorkTypes { get; } =
Enum.GetValues<VPet_Simulator.Core.GraphHelper.Work.WorkType>().ToFrozenSet();
#region Id
#region ID
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _id = string.Empty;
/// <summary>
/// Id
/// ID
/// </summary>
public string ID
{
@ -125,6 +125,15 @@ public class WorkModel : I18nModel<I18nWorkModel>
}
#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
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _graph = string.Empty;
@ -450,28 +459,10 @@ public class WorkModel : I18nModel<I18nWorkModel>
public void Close()
{
//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 x:Key="ListBox_ShowLangs" TargetType="ListBox">
<ListBox
ItemsSource="{Binding I18nData.CultureNames}"
ItemsSource="{Binding I18nResource.CultureDatas.ObservableKeys}"
ScrollViewer.VerticalScrollBarVisibility="Auto"
SelectedItem="{Binding I18nData.CultureName}">
SelectedItem="{Binding I18nResource.CurrentCulture}">
<ListBox.ItemContainerStyle>
<Style BasedOn="{StaticResource {x:Type ListBoxItem}}" TargetType="ListBoxItem">
<Setter Property="Content" Value="{Binding}" />

View File

@ -258,19 +258,6 @@ public static class NativeExtensions
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)
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>
<UseWPF>true</UseWPF>
<LangVersion>preview</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\food.png" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="VPet-Simulator.Core" Version="1.1.0.1" />
<PackageReference Include="VPet-Simulator.Windows.Interface" 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.5" />
<PackageReference Include="LinePutScript" Version="1.11.6" />
<PackageReference Include="LinePutScript.Localization.WPF" Version="1.0.6" />
<PackageReference Include="Ookii.Dialogs.Wpf" Version="5.0.1" />
<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" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="HKW.Utils" Version="1.2.6" />
<PackageReference Include="HKW.WPF" Version="1.0.3" />
<PackageReference Include="HKW.Utils" Version="1.2.13" />
<PackageReference Include="HKW.WPF" Version="1.0.4" />
<PackageReference Include="Mapster" Version="7.4.0" />
</ItemGroup>
</Project>

View File

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

View File

@ -25,7 +25,11 @@ public class FoodEditWindowVM : ObservableObjectX
}
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
public FoodModel? OldFood { get; set; }

View File

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

View File

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

View File

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

View File

@ -23,7 +23,10 @@ public class PetEditWindowVM : ObservableObjectX
}
#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; }
#region Pet

View File

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

View File

@ -92,8 +92,10 @@ public class WorkEditWindowVM : ObservableObjectX
}
}
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
public PetModel CurrentPet { get; set; } = null!;
public WorkModel? OldWork { get; set; }

View File

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

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -51,7 +52,11 @@ public partial class AddCultureWindow : WindowX
MessageBox.Show("文化不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
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);
return;
@ -62,10 +67,8 @@ public partial class AddCultureWindow : WindowX
private void Hyperlink_Click(object? sender, RoutedEventArgs e)
{
Process.Start(
new ProcessStartInfo(
"https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-lcid/a9eac961-e77d-41a6-90a5-ce1a8b0cdb9c"
)
NativeUtils.OpenLink(
"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" />
</Grid.RowDefinitions>
<!--<Label Content="{ll:Str 动画Id}" />
<!--<Label Content="{ll:Str 动画ID}" />
<TextBox Grid.Column="1" />-->
<Label Content="{ll:Str 动画类型}" />
<TextBlock Grid.Column="1" Text="{Binding Anime.GraphType}" />

View File

@ -45,7 +45,7 @@
Style="{DynamicResource StandardComboBoxStyle}">
<ComboBox.ItemContainerStyle>
<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.Value>
<MultiBinding Converter="{StaticResource AllTrueToCollapsedConverter}">

View File

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

View File

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

View File

@ -38,7 +38,7 @@ public partial class ClickTextEditWindow : Window
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);
return;
@ -51,7 +51,7 @@ public partial class ClickTextEditWindow : Window
MessageBox.Show("此ID已存在".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
if (string.IsNullOrEmpty(ViewModel.ClickText.CurrentI18nData.Text))
if (string.IsNullOrWhiteSpace(ViewModel.ClickText.Text))
{
MessageBox.Show("文本不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -39,7 +39,7 @@ public partial class LowTextEditWindow : Window
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);
return;
@ -52,7 +52,7 @@ public partial class LowTextEditWindow : Window
MessageBox.Show("此ID已存在".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
if (string.IsNullOrEmpty(ViewModel.LowText.CurrentI18nData.Text))
if (string.IsNullOrWhiteSpace(ViewModel.LowText.Text))
{
MessageBox.Show("文本不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return;

View File

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

View File

@ -119,7 +119,7 @@
Grid.Row="4"
Grid.Column="1"
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 模组介绍}" />
<TextBox
x:Name="TextBox_Description"
@ -129,7 +129,7 @@
VerticalContentAlignment="Top"
d:Text="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
pu:TextBoxHelper.Watermark="{ll:Str 模组介绍}"
Text="{Binding ModInfo.CurrentI18nData.Description, UpdateSourceTrigger=PropertyChanged}"
Text="{Binding ModInfo.Description, UpdateSourceTrigger=PropertyChanged}"
TextWrapping="Wrap" />
</Grid>
</ScrollViewer>
@ -279,9 +279,9 @@
x:Name="ListBox_Cultures"
Grid.Row="1"
d:ItemsSource="{d:SampleData ItemCount=5}"
ItemsSource="{Binding I18nData.CultureNames}"
ItemsSource="{Binding I18nResource.CultureDatas.ObservableKeys}"
ScrollViewer.VerticalScrollBarVisibility="Auto"
SelectedItem="{Binding I18nData.CultureName}">
SelectedItem="{Binding I18nResource.CurrentCulture}">
<ListBox.ItemContainerStyle>
<Style BasedOn="{StaticResource {x:Type ListBoxItem}}" TargetType="ListBoxItem">
<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.Imaging;
using System.Windows.Shapes;
using HKW.HKWUtils.Extensions;
using LinePutScript.Localization.WPF;
using Microsoft.Win32;
using Panuon.WPF;
@ -72,7 +73,7 @@ public partial class ModEditWindow : WindowX
/// </summary>
public void InitializeData()
{
if (I18nHelper.Current.CultureNames.Count == 0)
if (ModInfoModel.Current.I18nResource.CultureDatas.HasValue() is false)
{
if (
MessageBox.Show("未添加任何文化,确定要添加文化吗?".Translate(), "", MessageBoxButton.YesNo)
@ -81,16 +82,20 @@ public partial class ModEditWindow : WindowX
return;
ViewModel.AddCultureCommand_ExecuteCommand();
if (
I18nHelper.Current.CultureNames.Count == 0
ModInfoModel.Current.I18nResource.CultureDatas.HasValue() is false
|| MessageBox.Show(
"需要将文化 {0} 设为主要文化吗?".Translate(I18nHelper.Current.CultureNames.First()),
"需要将文化 {0} 设为主要文化吗?".Translate(
ModInfoModel.Current.I18nResource.CultureDatas.First().Key.Name
),
"",
MessageBoxButton.YesNo
)
is not MessageBoxResult.Yes
)
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
Grid.Row="3"
Grid.Column="1"
Text="{Binding Pet.CurrentI18nData.Description}" />-->
Text="{Binding Pet.Description}" />-->
</Grid>
</Grid>
<Grid Grid.Column="1">

View File

@ -45,7 +45,7 @@
Style="{DynamicResource StandardComboBoxStyle}">
<ComboBox.ItemContainerStyle>
<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.Value>
<MultiBinding Converter="{StaticResource AllTrueToCollapsedConverter}">

View File

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

View File

@ -49,15 +49,15 @@ public partial class PetEditWindow : Window
{
if (string.IsNullOrWhiteSpace(ViewModel.Pet.ID))
{
MessageBox.Show("Id不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
MessageBox.Show("ID不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
if (string.IsNullOrWhiteSpace(ViewModel.Pet.CurrentI18nData.Name))
if (string.IsNullOrWhiteSpace(ViewModel.Pet.Name))
{
MessageBox.Show("名称不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
if (string.IsNullOrWhiteSpace(ViewModel.Pet.CurrentI18nData.PetName))
if (string.IsNullOrWhiteSpace(ViewModel.Pet.PetName))
{
MessageBox.Show(
"宠物名称不可为空".Translate(),
@ -72,7 +72,7 @@ public partial class PetEditWindow : Window
&& 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;
}
IsCancel = false;

View File

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

View File

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

View File

@ -48,7 +48,7 @@ public partial class SelectTextEditWindow : Window
{
if (string.IsNullOrWhiteSpace(ViewModel.SelectText.ID))
{
MessageBox.Show("Id不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
MessageBox.Show("ID不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
if (
@ -56,10 +56,10 @@ public partial class SelectTextEditWindow : Window
&& 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;
}
if (string.IsNullOrWhiteSpace(ViewModel.SelectText.CurrentI18nData.Choose))
if (string.IsNullOrWhiteSpace(ViewModel.SelectText.Choose))
{
MessageBox.Show(
"选项名不可为空".Translate(),
@ -69,7 +69,7 @@ public partial class SelectTextEditWindow : Window
);
return;
}
if (string.IsNullOrWhiteSpace(ViewModel.SelectText.CurrentI18nData.Text))
if (string.IsNullOrWhiteSpace(ViewModel.SelectText.Text))
{
MessageBox.Show("文本不可为空".Translate(), "", MessageBoxButton.OK, MessageBoxImage.Warning);
return;

View File

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

View File

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

View File

@ -48,7 +48,7 @@
Style="{DynamicResource StandardComboBoxStyle}">
<ComboBox.ItemContainerStyle>
<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.Value>
<MultiBinding Converter="{StaticResource AllTrueToCollapsedConverter}">
@ -111,12 +111,12 @@
IsReadOnly="True"
SortMemberPath="ID" />
<DataGridTextColumn
Binding="{Binding CurrentI18nData.Name}"
Binding="{Binding Name}"
CanUserSort="True"
ElementStyle="{DynamicResource TextBlock_LeftCenter}"
Header="{ll:Str 工作名称}"
IsReadOnly="True"
SortMemberPath="CurrentI18nData.Name" />
SortMemberPath="Name" />
<DataGridTextColumn
Binding="{Binding WorkType}"
CanUserSort="True"