978 lines
36 KiB
C#
978 lines
36 KiB
C#
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
using System.IO;
|
||
using System.Xml.Serialization;
|
||
using System;
|
||
using System.Linq;
|
||
using TMPro;
|
||
using System.Reflection;
|
||
|
||
namespace LanguageManager
|
||
{
|
||
public enum LanguageMode
|
||
{
|
||
InternalDatabase,
|
||
ExternalFiles,
|
||
ComponentBased,
|
||
GlobalExternalFiles // Additional mode, if necessary
|
||
}
|
||
|
||
[System.Serializable]
|
||
public class Language
|
||
{
|
||
[Tooltip("The unique identifier for the language.")]
|
||
public string LanguageID;
|
||
|
||
[Tooltip("The display title for the language.")]
|
||
public string LanguageTitle;
|
||
|
||
[Tooltip("The icon representing the language.")]
|
||
public Sprite LanguageIcon;
|
||
|
||
[Tooltip("If true, the font asset will be swapped when changing the language.")]
|
||
public bool changeFontOnSwap;
|
||
|
||
[Tooltip("The TextMeshPro font asset to be used when the language is active.")]
|
||
public TMP_FontAsset fontAssetTextMesh;
|
||
|
||
[Tooltip("The Unity UI font asset to be used when the language is active.")]
|
||
public Font fontAsset;
|
||
|
||
[Tooltip("If true, the text will be displayed in bold.")]
|
||
public bool applyBold;
|
||
|
||
[Tooltip("If true, all text will be converted to uppercase.")]
|
||
public bool applyUppercase;
|
||
}
|
||
|
||
[System.Serializable]
|
||
public class Translation
|
||
{
|
||
public string LanguageID;
|
||
public string TranslatedText;
|
||
}
|
||
|
||
[System.Serializable]
|
||
public class TextEntry
|
||
{
|
||
public string TextID;
|
||
public List<Translation> Translations = new List<Translation>();
|
||
}
|
||
|
||
|
||
public class LanguageManager : MonoBehaviour
|
||
{
|
||
public static LanguageManager Instance;
|
||
public bool disableTMPWarnings;
|
||
public bool enableTextFormatting;
|
||
public LanguageMode languageMode;
|
||
public string currentLanguageID;
|
||
|
||
public List<Language> Languages = new List<Language>();
|
||
public List<TextEntry> TextEntries = new List<TextEntry>();
|
||
|
||
public delegate void OnLanguageChanged();
|
||
public static event OnLanguageChanged onLanguageChanged;
|
||
|
||
private Dictionary<string, string> externalTranslations = new Dictionary<string, string>();
|
||
|
||
private void Awake()
|
||
{
|
||
if (disableTMPWarnings)
|
||
{
|
||
DisableTMPWarnings();
|
||
}
|
||
if (Instance == null)
|
||
{
|
||
Instance = this;
|
||
DontDestroyOnLoad(gameObject);
|
||
}
|
||
else
|
||
{
|
||
Destroy(gameObject);
|
||
}
|
||
|
||
string savedLanguage = PlayerPrefs.GetString("SelectedLanguage", currentLanguageID);
|
||
SetLanguage(savedLanguage);
|
||
}
|
||
|
||
private void Start()
|
||
{
|
||
if (languageMode == LanguageMode.InternalDatabase)
|
||
{
|
||
Debug.Log("InternalDatabase mode selected.");
|
||
// Data is already available in the internal lists
|
||
}
|
||
else if (languageMode == LanguageMode.ExternalFiles)
|
||
{
|
||
Debug.Log("ExternalFiles mode selected.");
|
||
LoadExternalLanguageFiles();
|
||
}
|
||
else if (languageMode == LanguageMode.GlobalExternalFiles)
|
||
{
|
||
Debug.Log("GlobalExternalFiles mode selected.");
|
||
LoadGlobalLanguageFile();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Disables TextMeshPro warnings by setting the private m_warningsDisabled field to true.
|
||
/// </summary>
|
||
private void DisableTMPWarnings()
|
||
{
|
||
TMP_Settings settings = TMP_Settings.instance;
|
||
if (settings != null)
|
||
{
|
||
FieldInfo field = typeof(TMP_Settings).GetField("m_warningsDisabled", BindingFlags.NonPublic | BindingFlags.Instance);
|
||
if (field != null)
|
||
{
|
||
field.SetValue(settings, true);
|
||
Debug.Log("TMP warnings disabled successfully.");
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning("Unable to find the field m_warningsDisabled in TMP_Settings.");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning("TMP_Settings instance not found. Make sure TMP Settings asset exists in Resources.");
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Sets the current language by its ID, updates the translations, and saves the selection locally.
|
||
/// </summary>
|
||
/// <param name="languageID">The ID of the language to set.</param>
|
||
public void SetLanguage(string languageID)
|
||
{
|
||
if (string.IsNullOrEmpty(languageID))
|
||
{
|
||
Debug.LogError("SetLanguage called with null or empty languageID.");
|
||
return;
|
||
}
|
||
|
||
currentLanguageID = languageID;
|
||
|
||
if (languageMode == LanguageMode.ExternalFiles)
|
||
{
|
||
LoadExternalLanguageFiles();
|
||
}
|
||
else if (languageMode == LanguageMode.GlobalExternalFiles)
|
||
{
|
||
LoadGlobalLanguageFile();
|
||
}
|
||
|
||
// Save the selected language locally
|
||
PlayerPrefs.SetString("SelectedLanguage", languageID);
|
||
PlayerPrefs.Save();
|
||
// Notify all components that the language has changed
|
||
onLanguageChanged?.Invoke();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Loads translations from individual language files in StreamingAssets. Supports JSON, XML, and CSV formats.
|
||
/// </summary>
|
||
private void LoadExternalLanguageFiles()
|
||
{
|
||
externalTranslations.Clear();
|
||
|
||
// Define the path to the Languages folder
|
||
string languagesFolderPath = Path.Combine(Application.streamingAssetsPath, "Languages");
|
||
|
||
// Ensure the folder exists
|
||
if (!Directory.Exists(languagesFolderPath))
|
||
{
|
||
Debug.LogError($"Languages folder not found at {languagesFolderPath}");
|
||
return;
|
||
}
|
||
|
||
try
|
||
{
|
||
// Load the available languages based on the file names
|
||
PopulateAvailableLanguagesFromFiles(languagesFolderPath);
|
||
|
||
// Define possible file paths for the current language file
|
||
string jsonFilePath = Path.Combine(languagesFolderPath, currentLanguageID + ".json");
|
||
string xmlFilePath = Path.Combine(languagesFolderPath, currentLanguageID + ".xml");
|
||
string csvFilePath = Path.Combine(languagesFolderPath, currentLanguageID + ".csv");
|
||
|
||
// Check which format exists and load the language file
|
||
if (File.Exists(jsonFilePath))
|
||
{
|
||
LoadExternalLanguageFromJSON(jsonFilePath);
|
||
}
|
||
else if (File.Exists(xmlFilePath))
|
||
{
|
||
LoadExternalLanguageFromXML(xmlFilePath);
|
||
}
|
||
else if (File.Exists(csvFilePath))
|
||
{
|
||
LoadExternalLanguageFromCSV(csvFilePath);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError($"No language file found for {currentLanguageID} in JSON, XML, or CSV format.");
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError($"Error loading external language file: {e.Message}");
|
||
}
|
||
}
|
||
|
||
private void PopulateAvailableLanguagesFromFiles(string folderPath)
|
||
{
|
||
Languages.Clear();
|
||
|
||
// Get all language files in the folder (supports .json, .xml, and .csv)
|
||
string[] languageFiles = Directory.GetFiles(folderPath, "*.*")
|
||
.Where(file => (file.EndsWith(".json") || file.EndsWith(".xml") || file.EndsWith(".csv"))
|
||
&& !Path.GetFileName(file).ToLower().Contains("global")) // Filter out "global" files
|
||
.ToArray();
|
||
|
||
foreach (string filePath in languageFiles)
|
||
{
|
||
// Extract the language ID from the file name (e.g., "es.json" -> "es")
|
||
string fileName = Path.GetFileNameWithoutExtension(filePath);
|
||
|
||
// Create a new language entry with the file name as the LanguageID and LanguageTitle
|
||
Language newLanguage = new Language
|
||
{
|
||
LanguageID = fileName,
|
||
LanguageTitle = fileName // You can set this to something more user-friendly if needed
|
||
};
|
||
|
||
// Add the language to the list
|
||
Languages.Add(newLanguage);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Loads external language file from a JSON file.
|
||
/// </summary>
|
||
private void LoadExternalLanguageFromJSON(string filePath)
|
||
{
|
||
try
|
||
{
|
||
// Read the JSON content from the file
|
||
string jsonContent = File.ReadAllText(filePath);
|
||
|
||
// Deserializing the new structure which contains "Translations" directly
|
||
var loadedTranslations = JsonUtility.FromJson<TranslationListWrapper>(jsonContent);
|
||
|
||
if (loadedTranslations != null && loadedTranslations.Translations != null)
|
||
{
|
||
// Populate externalTranslations dictionary
|
||
foreach (var translation in loadedTranslations.Translations)
|
||
{
|
||
externalTranslations[translation.TextID] = translation.TranslatedText;
|
||
}
|
||
Debug.Log("Language file loaded successfully from JSON.");
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("Failed to deserialize the JSON file or it is empty.");
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError($"Error loading JSON language file: {e.Message}");
|
||
}
|
||
}
|
||
|
||
// Wrapper class for the new JSON format
|
||
[System.Serializable]
|
||
public class TranslationListWrapper
|
||
{
|
||
public List<TranslationSimple> Translations;
|
||
}
|
||
|
||
// Simpler structure for individual translations in the new JSON format
|
||
[System.Serializable]
|
||
public class TranslationSimple
|
||
{
|
||
public string TextID;
|
||
public string TranslatedText;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Loads external language file from an XML file.
|
||
/// </summary>
|
||
private void LoadExternalLanguageFromXML(string filePath)
|
||
{
|
||
try
|
||
{
|
||
string xmlContent = File.ReadAllText(filePath);
|
||
LanguageDataWrapper loadedData = null;
|
||
|
||
XmlSerializer serializer = new XmlSerializer(typeof(LanguageDataWrapper));
|
||
using (StringReader reader = new StringReader(xmlContent))
|
||
{
|
||
loadedData = (LanguageDataWrapper)serializer.Deserialize(reader);
|
||
}
|
||
|
||
if (loadedData != null)
|
||
{
|
||
foreach (TextEntry entry in loadedData.TextEntries)
|
||
{
|
||
Translation translation = entry.Translations.Find(t => t.LanguageID.Equals(currentLanguageID, StringComparison.OrdinalIgnoreCase));
|
||
if (translation != null)
|
||
{
|
||
externalTranslations[entry.TextID] = translation.TranslatedText;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("Failed to deserialize the XML file.");
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError($"Error loading XML language file: {e.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Loads external language file from a CSV file.
|
||
/// </summary>
|
||
private void LoadExternalLanguageFromCSV(string filePath)
|
||
{
|
||
try
|
||
{
|
||
using (StreamReader reader = new StreamReader(filePath))
|
||
{
|
||
string headerLine = reader.ReadLine();
|
||
string[] headers = ParseCSVLine(headerLine);
|
||
|
||
while (!reader.EndOfStream)
|
||
{
|
||
string line = reader.ReadLine();
|
||
string[] fields = ParseCSVLine(line);
|
||
|
||
if (fields.Length > 0)
|
||
{
|
||
string textID = fields[0];
|
||
for (int i = 1; i < fields.Length; i++)
|
||
{
|
||
if (headers[i].Equals(currentLanguageID, StringComparison.OrdinalIgnoreCase))
|
||
{
|
||
externalTranslations[textID] = fields[i];
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError($"Error loading CSV language file: {e.Message}");
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Loads all translations from a global language file stored in StreamingAssets. Supports XML, JSON, and CSV formats.
|
||
/// </summary>
|
||
private void LoadGlobalLanguageFile()
|
||
{
|
||
externalTranslations.Clear();
|
||
|
||
// Definindo os poss<73>veis caminhos dos arquivos em diferentes formatos
|
||
string xmlFilePath = Path.Combine(Application.streamingAssetsPath, "Languages", "globalLanguages.xml");
|
||
string jsonFilePath = Path.Combine(Application.streamingAssetsPath, "Languages", "globalLanguages.json");
|
||
string csvFilePath = Path.Combine(Application.streamingAssetsPath, "Languages", "globalLanguages.csv");
|
||
|
||
try
|
||
{
|
||
if (File.Exists(xmlFilePath))
|
||
{
|
||
LoadGlobalLanguageFromXML(xmlFilePath);
|
||
}
|
||
else if (File.Exists(jsonFilePath))
|
||
{
|
||
LoadGlobalLanguageFromJSON(jsonFilePath);
|
||
}
|
||
else if (File.Exists(csvFilePath))
|
||
{
|
||
LoadGlobalLanguageFromCSV(csvFilePath);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("No global language file found in XML, JSON, or CSV format.");
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError($"Error loading global language file: {e.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Loads the global language file from an XML file.
|
||
/// </summary>
|
||
private void LoadGlobalLanguageFromXML(string filePath)
|
||
{
|
||
try
|
||
{
|
||
string xmlContent = File.ReadAllText(filePath);
|
||
LanguageDataWrapper dataWrapper = null;
|
||
|
||
XmlSerializer serializer = new XmlSerializer(typeof(LanguageDataWrapper));
|
||
using (StringReader reader = new StringReader(xmlContent))
|
||
{
|
||
dataWrapper = (LanguageDataWrapper)serializer.Deserialize(reader);
|
||
}
|
||
|
||
if (dataWrapper != null)
|
||
{
|
||
this.Languages = dataWrapper.Languages;
|
||
this.TextEntries = dataWrapper.TextEntries;
|
||
PopulateExternalTranslations();
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("Failed to deserialize globalLanguages.xml or it is empty.");
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError($"Error loading XML language file: {e.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Loads the global language file from a JSON file.
|
||
/// </summary>
|
||
private void LoadGlobalLanguageFromJSON(string filePath)
|
||
{
|
||
try
|
||
{
|
||
string jsonContent = File.ReadAllText(filePath);
|
||
LanguageDataWrapper dataWrapper = JsonUtility.FromJson<LanguageDataWrapper>(jsonContent);
|
||
|
||
if (dataWrapper != null)
|
||
{
|
||
this.Languages = dataWrapper.Languages;
|
||
this.TextEntries = dataWrapper.TextEntries;
|
||
PopulateExternalTranslations();
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("Failed to deserialize globalLanguages.json or it is empty.");
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError($"Error loading JSON language file: {e.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Loads the global language file from a CSV file.
|
||
/// </summary>
|
||
private void LoadGlobalLanguageFromCSV(string filePath)
|
||
{
|
||
try
|
||
{
|
||
using (StreamReader reader = new StreamReader(filePath))
|
||
{
|
||
string headerLine = reader.ReadLine();
|
||
string[] headers = ParseCSVLine(headerLine);
|
||
|
||
Languages.Clear();
|
||
TextEntries.Clear();
|
||
|
||
// Populate languages from the header
|
||
for (int i = 1; i < headers.Length; i++)
|
||
{
|
||
Language language = new Language { LanguageID = headers[i], LanguageTitle = headers[i] };
|
||
Languages.Add(language);
|
||
}
|
||
|
||
// Populate text entries
|
||
while (!reader.EndOfStream)
|
||
{
|
||
string line = reader.ReadLine();
|
||
string[] fields = ParseCSVLine(line);
|
||
if (fields.Length > 0)
|
||
{
|
||
TextEntry entry = new TextEntry { TextID = fields[0] };
|
||
for (int i = 1; i < fields.Length; i++)
|
||
{
|
||
Translation translation = new Translation
|
||
{
|
||
LanguageID = headers[i],
|
||
TranslatedText = fields[i]
|
||
};
|
||
entry.Translations.Add(translation);
|
||
}
|
||
TextEntries.Add(entry);
|
||
}
|
||
}
|
||
}
|
||
|
||
PopulateExternalTranslations();
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError($"Error loading CSV language file: {e.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Populates the externalTranslations dictionary based on the current language ID.
|
||
/// </summary>
|
||
private void PopulateExternalTranslations()
|
||
{
|
||
externalTranslations.Clear();
|
||
foreach (TextEntry entry in TextEntries)
|
||
{
|
||
Translation translation = entry.Translations.Find(t => t.LanguageID.Equals(currentLanguageID, StringComparison.OrdinalIgnoreCase));
|
||
if (translation != null)
|
||
{
|
||
externalTranslations[entry.TextID] = translation.TranslatedText;
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning($"Translation for LanguageID '{currentLanguageID}' not found in TextEntry '{entry.TextID}'.");
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Exports language data to a JSON file.
|
||
/// </summary>
|
||
/// <param name="filePath">The file path to save the JSON data.</param>
|
||
public void ExportLanguagesToJSON(string filePath)
|
||
{
|
||
try
|
||
{
|
||
LanguageDataWrapper database = new LanguageDataWrapper
|
||
{
|
||
Languages = this.Languages,
|
||
TextEntries = this.TextEntries
|
||
};
|
||
string json = JsonUtility.ToJson(database, true);
|
||
File.WriteAllText(filePath, json);
|
||
|
||
Debug.Log("Exported to JSON successfully.");
|
||
}
|
||
catch (System.Exception e)
|
||
{
|
||
Debug.LogError("Error exporting to JSON: " + e.Message);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Imports language data from a JSON file.
|
||
/// </summary>
|
||
/// <param name="filePath">The file path to import the JSON data from.</param>
|
||
public void ImportLanguagesFromJSON(string filePath)
|
||
{
|
||
try
|
||
{
|
||
if (File.Exists(filePath))
|
||
{
|
||
string json = File.ReadAllText(filePath);
|
||
LanguageDataWrapper database = JsonUtility.FromJson<LanguageDataWrapper>(json);
|
||
this.Languages = database.Languages;
|
||
this.TextEntries = database.TextEntries;
|
||
|
||
Debug.Log("Imported from JSON successfully.");
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("File not found: " + filePath);
|
||
}
|
||
}
|
||
catch (System.Exception e)
|
||
{
|
||
Debug.LogError("Error importing from JSON: " + e.Message);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Exports language data to a CSV file.
|
||
/// </summary>
|
||
public void ExportLanguagesToCSV(string filePath)
|
||
{
|
||
try
|
||
{
|
||
using (StreamWriter writer = new StreamWriter(filePath))
|
||
{
|
||
// Write header
|
||
writer.Write("textID");
|
||
foreach (Language language in Languages)
|
||
{
|
||
writer.Write($",{language.LanguageID}");
|
||
}
|
||
writer.WriteLine();
|
||
|
||
// Write text entries
|
||
foreach (TextEntry entry in TextEntries)
|
||
{
|
||
writer.Write(entry.TextID);
|
||
foreach (Language language in Languages)
|
||
{
|
||
string translatedText = "";
|
||
Translation translation = entry.Translations.Find(t => t.LanguageID == language.LanguageID);
|
||
if (translation != null)
|
||
{
|
||
translatedText = translation.TranslatedText;
|
||
}
|
||
writer.Write($",\"{translatedText}\"");
|
||
}
|
||
writer.WriteLine();
|
||
}
|
||
}
|
||
|
||
Debug.Log("Exported to CSV successfully.");
|
||
}
|
||
catch (System.Exception e)
|
||
{
|
||
Debug.LogError("Error exporting to CSV: " + e.Message);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Imports language data from a CSV file.
|
||
/// </summary>
|
||
public void ImportLanguagesFromCSV(string filePath)
|
||
{
|
||
try
|
||
{
|
||
if (File.Exists(filePath))
|
||
{
|
||
using (StreamReader reader = new StreamReader(filePath))
|
||
{
|
||
string headerLine = reader.ReadLine();
|
||
string[] headers = ParseCSVLine(headerLine);
|
||
|
||
// Clear existing languages and text entries
|
||
Languages.Clear();
|
||
TextEntries.Clear();
|
||
|
||
// The first column is textID, the rest are LanguageIDs
|
||
for (int i = 1; i < headers.Length; i++)
|
||
{
|
||
Language language = new Language
|
||
{
|
||
LanguageID = headers[i],
|
||
LanguageTitle = headers[i]
|
||
};
|
||
Languages.Add(language);
|
||
}
|
||
|
||
// Read text entries
|
||
while (!reader.EndOfStream)
|
||
{
|
||
string line = reader.ReadLine();
|
||
string[] fields = ParseCSVLine(line);
|
||
if (fields.Length > 0)
|
||
{
|
||
TextEntry entry = new TextEntry
|
||
{
|
||
TextID = fields[0]
|
||
};
|
||
for (int i = 1; i < fields.Length; i++)
|
||
{
|
||
Translation translation = new Translation
|
||
{
|
||
LanguageID = headers[i],
|
||
TranslatedText = fields[i]
|
||
};
|
||
entry.Translations.Add(translation);
|
||
}
|
||
TextEntries.Add(entry);
|
||
}
|
||
}
|
||
}
|
||
|
||
Debug.Log("Imported from CSV successfully.");
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("File not found: " + filePath);
|
||
}
|
||
}
|
||
catch (System.Exception e)
|
||
{
|
||
Debug.LogError("Error importing from CSV: " + e.Message);
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// Exports the current language data to an XML file.
|
||
/// </summary>
|
||
/// <param name="filePath">The file path where the XML data will be saved.</param>
|
||
public void ExportLanguagesToXML(string filePath)
|
||
{
|
||
try
|
||
{
|
||
LanguageDataWrapper dataWrapper = new LanguageDataWrapper
|
||
{
|
||
Languages = this.Languages,
|
||
TextEntries = this.TextEntries
|
||
};
|
||
|
||
XmlSerializer serializer = new XmlSerializer(typeof(LanguageDataWrapper));
|
||
|
||
using (FileStream stream = new FileStream(filePath, FileMode.Create))
|
||
{
|
||
serializer.Serialize(stream, dataWrapper);
|
||
}
|
||
|
||
Debug.Log("Exported to XML successfully.");
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError("Error exporting to XML: " + e.Message);
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// Imports language data from an XML file.
|
||
/// </summary>
|
||
/// <param name="filePath">The file path to import the XML data from.</param>
|
||
/// <summary>
|
||
/// Imports language data from an XML file.
|
||
/// </summary>
|
||
/// <param name="filePath">The file path to import the XML data from.</param>
|
||
public void ImportLanguagesFromXML(string filePath)
|
||
{
|
||
try
|
||
{
|
||
if (File.Exists(filePath))
|
||
{
|
||
// Initialize the XML serializer with the type LanguageDataWrapper
|
||
XmlSerializer serializer = new XmlSerializer(typeof(LanguageDataWrapper));
|
||
|
||
// Open the file stream for reading
|
||
using (FileStream stream = new FileStream(filePath, FileMode.Open))
|
||
{
|
||
// Deserialize the XML data into a LanguageDataWrapper object
|
||
LanguageDataWrapper dataWrapper = (LanguageDataWrapper)serializer.Deserialize(stream);
|
||
|
||
// Update the internal lists with the imported data
|
||
this.Languages = dataWrapper.Languages;
|
||
this.TextEntries = dataWrapper.TextEntries;
|
||
|
||
// Update the externalTranslations dictionary based on the currentLanguageID
|
||
externalTranslations.Clear();
|
||
foreach (TextEntry entry in TextEntries)
|
||
{
|
||
Translation translation = entry.Translations.Find(t => t.LanguageID.Equals(currentLanguageID, StringComparison.OrdinalIgnoreCase));
|
||
if (translation != null)
|
||
{
|
||
externalTranslations[entry.TextID] = translation.TranslatedText;
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning($"Translation for LanguageID '{currentLanguageID}' not found in TextEntry '{entry.TextID}'.");
|
||
}
|
||
}
|
||
}
|
||
|
||
Debug.Log("Imported from XML successfully.");
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("File not found: " + filePath);
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError("Error importing from XML: " + e.Message);
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Exports an empty base model for translations in the selected format.
|
||
/// </summary>
|
||
/// <param name="format">The format to export (JSON, CSV, XML).</param>
|
||
/// <param name="filePath">The file path to save the base model.</param>
|
||
public void ExportBaseModel(string format, string filePath)
|
||
{
|
||
try
|
||
{
|
||
if (string.IsNullOrEmpty(filePath))
|
||
{
|
||
Debug.LogError("File path is not set.");
|
||
return;
|
||
}
|
||
|
||
if (format == "JSON")
|
||
{
|
||
// Export empty structures to JSON
|
||
string jsonContent = JsonUtility.ToJson(new LanguageDataWrapper
|
||
{
|
||
Languages = this.Languages,
|
||
TextEntries = new List<TextEntry>() // Empty list
|
||
}, true);
|
||
File.WriteAllText(filePath, jsonContent);
|
||
}
|
||
else if (format == "CSV")
|
||
{
|
||
// Export CSV file with headers including languages
|
||
using (StreamWriter writer = new StreamWriter(filePath))
|
||
{
|
||
// Write header with textID and LanguageIDs
|
||
writer.Write("textID");
|
||
foreach (Language language in Languages)
|
||
{
|
||
writer.Write($",{language.LanguageID}");
|
||
}
|
||
writer.WriteLine();
|
||
|
||
// No text entries, as it's a base model
|
||
}
|
||
}
|
||
else if (format == "XML")
|
||
{
|
||
// Export empty structures to XML
|
||
LanguageDataWrapper dataWrapper = new LanguageDataWrapper
|
||
{
|
||
Languages = this.Languages,
|
||
TextEntries = new List<TextEntry>() // Empty list
|
||
};
|
||
XmlSerializer serializer = new XmlSerializer(typeof(LanguageDataWrapper));
|
||
using (FileStream stream = new FileStream(filePath, FileMode.Create))
|
||
{
|
||
serializer.Serialize(stream, dataWrapper);
|
||
}
|
||
}
|
||
|
||
Debug.Log("Base model export completed.");
|
||
}
|
||
catch (System.Exception e)
|
||
{
|
||
Debug.LogError("Error exporting base model: " + e.Message);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Helper method to parse CSV lines considering possible commas within quotes.
|
||
/// </summary>
|
||
/// <param name="line">The CSV line to parse.</param>
|
||
/// <returns>Array of parsed strings.</returns>
|
||
private string[] ParseCSVLine(string line)
|
||
{
|
||
List<string> result = new List<string>();
|
||
bool inQuotes = false;
|
||
string value = "";
|
||
|
||
foreach (char c in line)
|
||
{
|
||
if (c == '\"')
|
||
{
|
||
inQuotes = !inQuotes;
|
||
}
|
||
else if (c == ',' && !inQuotes)
|
||
{
|
||
result.Add(value);
|
||
value = "";
|
||
}
|
||
else
|
||
{
|
||
value += c;
|
||
}
|
||
}
|
||
result.Add(value);
|
||
|
||
return result.ToArray();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Retrieves the translated text for a given text ID based on the selected language.
|
||
/// If the text ID is not found or the translation for the current language does not exist, returns an empty string.
|
||
/// If enableTextFormatting is true, the returned text is processed for escape characters and formatting markers.
|
||
/// </summary>
|
||
/// <param name="textID">The text ID to retrieve.</param>
|
||
/// <returns>The translated text for the provided text ID in the current language.</returns>
|
||
public string GetTextEntryByID(string textID)
|
||
{
|
||
string result = string.Empty;
|
||
|
||
if (languageMode == LanguageMode.InternalDatabase)
|
||
{
|
||
TextEntry entry = TextEntries.Find(e => e.TextID.Equals(textID, StringComparison.OrdinalIgnoreCase));
|
||
if (entry != null)
|
||
{
|
||
Translation translation = entry.Translations.Find(t => t.LanguageID.Equals(currentLanguageID, StringComparison.OrdinalIgnoreCase));
|
||
if (translation != null)
|
||
{
|
||
result = translation.TranslatedText;
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning($"Translation for LanguageID '{currentLanguageID}' not found in TextEntry '{textID}'.");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning($"TextEntry with TextID '{textID}' not found.");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (externalTranslations.ContainsKey(textID))
|
||
{
|
||
result = externalTranslations[textID];
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning($"External translation for TextID '{textID}' not found.");
|
||
}
|
||
}
|
||
|
||
// Process text formatting if enableTextFormatting is true
|
||
if (enableTextFormatting)
|
||
{
|
||
result = ProcessTextFormatting(result);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Processes the input text by converting common escape sequences and custom formatting markers
|
||
/// to their corresponding display characters or tags.
|
||
/// For example, converts "\\n" to a newline, "[b]...[/b]" to "<b>...</b>", etc.
|
||
/// </summary>
|
||
/// <param name="input">The raw input text to process.</param>
|
||
/// <returns>The processed text with formatting applied.</returns>
|
||
private string ProcessTextFormatting(string input)
|
||
{
|
||
if (string.IsNullOrEmpty(input))
|
||
return input;
|
||
|
||
input = input.Replace("\\n", "\n");
|
||
input = input.Replace("\\t", "\t");
|
||
input = input.Replace("\\r", "\r");
|
||
input = input.Replace("\\\"", "\"");
|
||
input = input.Replace("\\\\", "\\");
|
||
|
||
input = input.Replace("[b]", "<b>").Replace("[/b]", "</b>");
|
||
input = input.Replace("[i]", "<i>").Replace("[/i]", "</i>");
|
||
|
||
return input;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Gets the current language ID.
|
||
/// </summary>
|
||
/// <returns>The current language ID.</returns>
|
||
public string GetCurrentLanguage()
|
||
{
|
||
return currentLanguageID;
|
||
}
|
||
}
|
||
}
|