diff --git a/docs/release-notes.md b/docs/release-notes.md
index 5bf8a803..f9e8932d 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -6,6 +6,7 @@
* Added config option to disable console colors.
* SMAPI now prevents more errors/crashes due to invalid item data.
* Updated compatibility list.
+ * Improved translations.¹
* For the Console Commands mod:
* The date commands like `world_setday` now also set the `daysPlayed` stat, so in-game events/randomization match what you'd get if you played to that date normally (thanks to kdau!).
@@ -15,10 +16,13 @@
* Fixed rare intermittent "CGI application encountered an error" errors.
* For modders:
- * Extended `SDate` with `SeasonIndex`, `FromDaysSinceStart`, `FromWorldDate`, `ToWorldDate`, and `ToLocaleString` fields/methods (thanks to kdau!).
+ * Added `SDate` fields/methods: `SeasonIndex`, `FromDaysSinceStart`, `FromWorldDate`, `ToWorldDate`, and `ToLocaleString` (thanks to kdau!).
+ * Added `SDate` translations taken from the Lookup Anything mod.¹
* Fixed asset propagation on Linux/Mac for monster sprites, NPC dialogue, and NPC schedules.
* Fixed asset propagation for NPC dialogue sometimes causing a spouse to skip marriage dialogue or not allow kisses.
+¹ Date translations were taken from the Lookup Anything mod; thanks to FixThisPlz (improved Russian), LeecanIt (added Italian), pomepome (added Japanese), S2SKY (added Korean), Sasara (added German), SteaNN (added Russian), ThomasGabrielDelavault (added Spanish), VincentRoth (added French), Yllelder (improved Spanish), and yuwenlan (added Chinese). Translations for Korean (partial), Hungarian, and Turkish were auto-generated based on the game translations.
+
## 3.4.1
Released 24 March 2020 for Stardew Valley 1.4.1 or later.
diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs
index 50e6ea1c..de9c955d 100644
--- a/src/SMAPI/Framework/SCore.cs
+++ b/src/SMAPI/Framework/SCore.cs
@@ -32,6 +32,7 @@ using StardewModdingAPI.Toolkit.Framework.Clients.WebApi;
using StardewModdingAPI.Toolkit.Framework.ModData;
using StardewModdingAPI.Toolkit.Serialization;
using StardewModdingAPI.Toolkit.Utilities;
+using StardewModdingAPI.Utilities;
using StardewValley;
using Object = StardewValley.Object;
using ThreadState = System.Threading.ThreadState;
@@ -176,6 +177,8 @@ namespace StardewModdingAPI.Framework
SCore.DeprecationManager = new DeprecationManager(this.Monitor, this.ModRegistry);
+ SDate.Translations = this.Translator;
+
// redirect direct console output
if (this.MonitorForGame.WriteToConsole)
this.ConsoleManager.OnMessageIntercepted += message => this.HandleConsoleMessage(this.MonitorForGame, message);
diff --git a/src/SMAPI/Program.cs b/src/SMAPI/Program.cs
index c26ae29a..715c8553 100644
--- a/src/SMAPI/Program.cs
+++ b/src/SMAPI/Program.cs
@@ -143,8 +143,8 @@ namespace StardewModdingAPI
}
// load SMAPI
- using (SCore core = new SCore(modsPath, writeToConsole))
- core.RunInteractively();
+ using SCore core = new SCore(modsPath, writeToConsole);
+ core.RunInteractively();
}
/// Write an error directly to the console and exit.
diff --git a/src/SMAPI/Utilities/SDate.cs b/src/SMAPI/Utilities/SDate.cs
index 36907714..4d4920ab 100644
--- a/src/SMAPI/Utilities/SDate.cs
+++ b/src/SMAPI/Utilities/SDate.cs
@@ -1,5 +1,6 @@
using System;
using System.Linq;
+using StardewModdingAPI.Framework;
using StardewValley;
namespace StardewModdingAPI.Utilities
@@ -19,6 +20,9 @@ namespace StardewModdingAPI.Utilities
/// The number of days in a season.
private readonly int DaysInSeason = 28;
+ /// The core SMAPI translations.
+ internal static Translator Translations;
+
/*********
** Accessors
@@ -126,16 +130,31 @@ namespace StardewModdingAPI.Utilities
return new WorldDate(this.Year, this.Season, this.Day);
}
- /// Get a string representation of the date. This is mainly intended for debugging or console messages.
+ /// Get an untranslated string representation of the date. This is mainly intended for debugging or console messages.
public override string ToString()
{
return $"{this.Day:00} {this.Season} Y{this.Year}";
}
/// Get a translated string representation of the date in the current game locale.
- public string ToLocaleString()
+ /// Whether to get a string which includes the year number.
+ public string ToLocaleString(bool withYear = true)
{
- return Utility.getDateStringFor(this.Day, this.SeasonIndex, this.Year);
+ // get fallback translation from game
+ string fallback = Utility.getDateStringFor(this.Day, this.SeasonIndex, this.Year);
+ if (SDate.Translations == null)
+ return fallback;
+
+ // get short format
+ string seasonName = Utility.getSeasonNameFromNumber(this.SeasonIndex);
+ return SDate.Translations
+ .Get(withYear ? "generic.date-with-year" : "generic.date", new
+ {
+ day = this.Day,
+ year = this.Year,
+ season = Utility.getSeasonNameFromNumber(this.SeasonIndex)
+ })
+ .Default(fallback);
}
/****
diff --git a/src/SMAPI/i18n/de.json b/src/SMAPI/i18n/de.json
index a8b3086f..47655a63 100644
--- a/src/SMAPI/i18n/de.json
+++ b/src/SMAPI/i18n/de.json
@@ -1,3 +1,9 @@
{
- "warn.invalid-content-removed": "Ungültiger Inhalt wurde entfernt, um einen Absturz zu verhindern (siehe SMAPI Konsole für weitere Informationen)."
+ // error messages
+ "warn.invalid-content-removed": "Ungültiger Inhalt wurde entfernt, um einen Absturz zu verhindern (siehe SMAPI Konsole für weitere Informationen).",
+
+ // short date format for SDate
+ "generic.date": "{{season}} {{day}}",
+ "generic.date-with-year": "{{season}} {{day}} im Jahr {{year}}"
+
}
diff --git a/src/SMAPI/i18n/default.json b/src/SMAPI/i18n/default.json
index 5a3e4a6e..ba46241b 100644
--- a/src/SMAPI/i18n/default.json
+++ b/src/SMAPI/i18n/default.json
@@ -1,3 +1,8 @@
{
- "warn.invalid-content-removed": "Invalid content was removed to prevent a crash (see the SMAPI console for info)."
+ // error messages
+ "warn.invalid-content-removed": "Invalid content was removed to prevent a crash (see the SMAPI console for info).",
+
+ // short date format for SDate
+ "generic.date": "{{season}} {{day}}",
+ "generic.date-with-year": "{{season}} {{day}} in year {{year}}"
}
diff --git a/src/SMAPI/i18n/es.json b/src/SMAPI/i18n/es.json
index f5a74dfe..dc77c4b7 100644
--- a/src/SMAPI/i18n/es.json
+++ b/src/SMAPI/i18n/es.json
@@ -1,3 +1,8 @@
{
- "warn.invalid-content-removed": "Se ha quitado contenido inválido para evitar un cierre forzoso (revisa la consola de SMAPI para más información)."
+ // error messages
+ "warn.invalid-content-removed": "Se ha quitado contenido inválido para evitar un cierre forzoso (revisa la consola de SMAPI para más información).",
+
+ // short date format for SDate
+ "generic.date": "{{season}} {{day}}",
+ "generic.date-with-year": "{{season}} {{day}} del año {{year}}"
}
diff --git a/src/SMAPI/i18n/fr.json b/src/SMAPI/i18n/fr.json
index 6d051025..3b3596ce 100644
--- a/src/SMAPI/i18n/fr.json
+++ b/src/SMAPI/i18n/fr.json
@@ -1,3 +1,8 @@
{
- "warn.invalid-content-removed": "Le contenu non valide a été supprimé afin d'éviter un plantage (voir la console de SMAPI pour plus d'informations)."
+ // error messages
+ "warn.invalid-content-removed": "Le contenu non valide a été supprimé afin d'éviter un plantage (voir la console de SMAPI pour plus d'informations).",
+
+ // short date format for SDate
+ "generic.date": "{{day}} {{season}}",
+ "generic.date-with-year": "{{day}} {{season}} de l'année {{year}}"
}
diff --git a/src/SMAPI/i18n/hu.json b/src/SMAPI/i18n/hu.json
index aa0c7546..d89d446f 100644
--- a/src/SMAPI/i18n/hu.json
+++ b/src/SMAPI/i18n/hu.json
@@ -1,3 +1,8 @@
{
- "warn.invalid-content-removed": "Érvénytelen elemek kerültek eltávolításra, hogy a játék ne omoljon össze (további információk a SMAPI konzolon)."
+ // error messages
+ "warn.invalid-content-removed": "Érvénytelen elemek kerültek eltávolításra, hogy a játék ne omoljon össze (további információk a SMAPI konzolon).",
+
+ // short date format for SDate
+ "generic.date": "{{season}} {{day}}",
+ "generic.date-with-year": "{{year}}. év {{season}} {{day}}"
}
diff --git a/src/SMAPI/i18n/it.json b/src/SMAPI/i18n/it.json
index 43493018..20c91b4f 100644
--- a/src/SMAPI/i18n/it.json
+++ b/src/SMAPI/i18n/it.json
@@ -1,3 +1,8 @@
{
- "warn.invalid-content-removed": "Contenuto non valido rimosso per prevenire un crash (Guarda la console di SMAPI per maggiori informazioni)."
+ // error messages
+ "warn.invalid-content-removed": "Contenuto non valido rimosso per prevenire un crash (Guarda la console di SMAPI per maggiori informazioni).",
+
+ // short date format for SDate
+ "generic.date": "{{day}} {{season}}",
+ "generic.date-with-year": "{{day}} {{season}} dell'anno {{year}}"
}
diff --git a/src/SMAPI/i18n/ja.json b/src/SMAPI/i18n/ja.json
index 9bbc285e..1c8d9f0e 100644
--- a/src/SMAPI/i18n/ja.json
+++ b/src/SMAPI/i18n/ja.json
@@ -1,3 +1,8 @@
{
- "warn.invalid-content-removed": "クラッシュを防ぐために無効なコンテンツを取り除きました (詳細はSMAPIコンソールを参照)"
+ // error messages
+ "warn.invalid-content-removed": "クラッシュを防ぐために無効なコンテンツを取り除きました (詳細はSMAPIコンソールを参照)",
+
+ // short date format for SDate
+ "generic.date": "{{season}} {{day}}日",
+ "generic.date-with-year": "{{year}}年目 {{season}} {{day}}日"
}
diff --git a/src/SMAPI/i18n/ko.json b/src/SMAPI/i18n/ko.json
new file mode 100644
index 00000000..6f60ad09
--- /dev/null
+++ b/src/SMAPI/i18n/ko.json
@@ -0,0 +1,8 @@
+{
+ // error messages
+ "warn.invalid-content-removed": "충돌을 방지하기 위해 잘못된 컨텐츠가 제거되었습니다 (자세한 내용은 SMAPI 콘솔 참조).",
+
+ // short date format for SDate
+ "generic.date": "{{season}} {{day}}",
+ "generic.date-with-year": "{{year}} 학년 {{season}} {{day}}"
+}
diff --git a/src/SMAPI/i18n/pt.json b/src/SMAPI/i18n/pt.json
index 59273680..8678a4f7 100644
--- a/src/SMAPI/i18n/pt.json
+++ b/src/SMAPI/i18n/pt.json
@@ -1,3 +1,8 @@
{
- "warn.invalid-content-removed": "Conteúdo inválido foi removido para prevenir uma falha (veja o console do SMAPI para mais informações)."
+ // error messages
+ "warn.invalid-content-removed": "Conteúdo inválido foi removido para prevenir uma falha (veja o console do SMAPI para mais informações).",
+
+ // short date format for SDate
+ "generic.date": "{{season}} {{day}}",
+ "generic.date-with-year": "{{season}} {{day}} no ano {{year}}"
}
diff --git a/src/SMAPI/i18n/ru.json b/src/SMAPI/i18n/ru.json
index a6a242fa..d773485a 100644
--- a/src/SMAPI/i18n/ru.json
+++ b/src/SMAPI/i18n/ru.json
@@ -1,3 +1,8 @@
{
- "warn.invalid-content-removed": "Недопустимое содержимое было удалено, чтобы предотвратить сбой (см. информацию в консоли SMAPI)"
+ // error messages
+ "warn.invalid-content-removed": "Недопустимое содержимое было удалено, чтобы предотвратить сбой (см. информацию в консоли SMAPI)",
+
+ // short date format for SDate
+ "generic.date": "{{season}}, {{day}}-е число",
+ "generic.date-with-year": "{{season}}, {{day}}-е число, {{year}}-й год"
}
diff --git a/src/SMAPI/i18n/tr.json b/src/SMAPI/i18n/tr.json
index 34229f2b..654e1acc 100644
--- a/src/SMAPI/i18n/tr.json
+++ b/src/SMAPI/i18n/tr.json
@@ -1,3 +1,8 @@
{
- "warn.invalid-content-removed": "Yanlış paketlenmiş bir içerik, oyunun çökmemesi için yüklenmedi (SMAPI konsol penceresinde detaylı bilgi mevcut)."
+ // error messages
+ "warn.invalid-content-removed": "Yanlış paketlenmiş bir içerik, oyunun çökmemesi için yüklenmedi (SMAPI konsol penceresinde detaylı bilgi mevcut).",
+
+ // short date format for SDate
+ "generic.date": "{{day}} {{season}}",
+ "generic.date-with-year": "{{day}} {{season}} года {{year}}"
}
diff --git a/src/SMAPI/i18n/zh.json b/src/SMAPI/i18n/zh.json
index 9c0e0c21..be485a79 100644
--- a/src/SMAPI/i18n/zh.json
+++ b/src/SMAPI/i18n/zh.json
@@ -1,3 +1,8 @@
{
- "warn.invalid-content-removed": "非法内容已移除以防游戏闪退(查看SMAPI控制台获得更多信息)"
+ // error messages
+ "warn.invalid-content-removed": "非法内容已移除以防游戏闪退(查看SMAPI控制台获得更多信息)",
+
+ // short date format for SDate
+ "generic.date": "{{season}}{{day}}日",
+ "generic.date-with-year": "第{{year}}年{{season}}{{day}}日"
}