196 lines
5.5 KiB
C#
196 lines
5.5 KiB
C#
using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEngine.Localization;
|
|
using UnityEngine.Localization.Tables;
|
|
using UnityEditor.Localization;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
public class LocalizationMultiTableImporter
|
|
{
|
|
[MenuItem("Localization/Import All Tables from CSV")]
|
|
public static void ImportAllLocalizationTables()
|
|
{
|
|
string path = EditorUtility.OpenFilePanel("Import Localization CSV", "", "csv");
|
|
if (string.IsNullOrEmpty(path)) return;
|
|
|
|
string rawCsv = File.ReadAllText(path, Encoding.UTF8);
|
|
var lines = SplitCSVRows(rawCsv);
|
|
if (lines.Count < 2)
|
|
{
|
|
Debug.LogError("CSV file is empty or missing header.");
|
|
return;
|
|
}
|
|
|
|
// Header: Table,Key,locale1,locale2,...
|
|
var header = SplitCSVLine(lines[0]);
|
|
if (header.Count < 3)
|
|
{
|
|
Debug.LogError("CSV header must contain at least 'Table,Key,<Locale>'");
|
|
return;
|
|
}
|
|
|
|
var localeCodes = header.Skip(2).ToList();
|
|
|
|
var locales = LocalizationEditorSettings.GetLocales();
|
|
var localeMap = locales.ToDictionary(l => l.Identifier.Code, l => l);
|
|
|
|
var collections = LocalizationEditorSettings.GetStringTableCollections();
|
|
|
|
for (int lineIndex = 1; lineIndex < lines.Count; lineIndex++)
|
|
{
|
|
var line = lines[lineIndex];
|
|
var cells = SplitCSVLine(line);
|
|
if (cells.Count < 2) continue;
|
|
|
|
string tableName = cells[0];
|
|
string key = cells[1];
|
|
|
|
var collection = collections.FirstOrDefault(c => c.TableCollectionName == tableName);
|
|
if (collection == null)
|
|
{
|
|
Debug.LogWarning($"Skipping unknown table: {tableName}");
|
|
continue;
|
|
}
|
|
|
|
for (int i = 0; i < localeCodes.Count; i++)
|
|
{
|
|
string localeCode = localeCodes[i];
|
|
if (!localeMap.TryGetValue(localeCode, out var locale)) continue;
|
|
|
|
var table = collection.GetTable(locale.Identifier) as StringTable;
|
|
if (table == null)
|
|
{
|
|
table = collection.AddNewTable(locale.Identifier) as StringTable;
|
|
}
|
|
|
|
var sharedData = collection.SharedData;
|
|
var sharedEntry = sharedData.GetEntry(key);
|
|
if (sharedEntry == null)
|
|
{
|
|
sharedEntry = sharedData.AddKey(key);
|
|
}
|
|
|
|
var entry = table.GetEntry(sharedEntry.Id);
|
|
if (entry == null)
|
|
{
|
|
entry = table.AddEntry(sharedEntry.Id, "");
|
|
}
|
|
|
|
if (i + 2 < cells.Count)
|
|
{
|
|
entry.Value = cells[i + 2];
|
|
}
|
|
|
|
EditorUtility.SetDirty(table);
|
|
}
|
|
}
|
|
|
|
AssetDatabase.SaveAssets();
|
|
Debug.Log(" Localization import complete!");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Splits CSV into rows, handling multiline quoted entries.
|
|
/// </summary>
|
|
private static List<string> SplitCSVRows(string csvText)
|
|
{
|
|
var rows = new List<string>();
|
|
var sb = new StringBuilder();
|
|
bool inQuotes = false;
|
|
|
|
for (int i = 0; i < csvText.Length; i++)
|
|
{
|
|
char c = csvText[i];
|
|
sb.Append(c);
|
|
|
|
if (c == '"')
|
|
{
|
|
// Check for escaped quote
|
|
if (i + 1 < csvText.Length && csvText[i + 1] == '"')
|
|
{
|
|
sb.Append('"');
|
|
i++;
|
|
}
|
|
else
|
|
{
|
|
inQuotes = !inQuotes;
|
|
}
|
|
}
|
|
else if ((c == '\n' || c == '\r') && !inQuotes)
|
|
{
|
|
// Handle Windows \r\n
|
|
if (c == '\r' && i + 1 < csvText.Length && csvText[i + 1] == '\n')
|
|
{
|
|
sb.Append('\n');
|
|
i++;
|
|
}
|
|
|
|
rows.Add(sb.ToString().TrimEnd('\r', '\n'));
|
|
sb.Clear();
|
|
}
|
|
}
|
|
|
|
if (sb.Length > 0)
|
|
rows.Add(sb.ToString().TrimEnd('\r', '\n'));
|
|
|
|
return rows;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Splits a CSV line into fields, handling commas and quotes correctly.
|
|
/// </summary>
|
|
private static List<string> SplitCSVLine(string line)
|
|
{
|
|
var result = new List<string>();
|
|
var sb = new StringBuilder();
|
|
bool inQuotes = false;
|
|
|
|
for (int i = 0; i < line.Length; i++)
|
|
{
|
|
char c = line[i];
|
|
|
|
if (inQuotes)
|
|
{
|
|
if (c == '"')
|
|
{
|
|
if (i + 1 < line.Length && line[i + 1] == '"')
|
|
{
|
|
sb.Append('"'); // escaped quote
|
|
i++;
|
|
}
|
|
else
|
|
{
|
|
inQuotes = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sb.Append(c);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (c == '"')
|
|
{
|
|
inQuotes = true;
|
|
}
|
|
else if (c == ',')
|
|
{
|
|
result.Add(sb.ToString());
|
|
sb.Clear();
|
|
}
|
|
else
|
|
{
|
|
sb.Append(c);
|
|
}
|
|
}
|
|
}
|
|
|
|
result.Add(sb.ToString());
|
|
return result;
|
|
}
|
|
}
|