Skip to content

Commit

Permalink
Migrate to CSV translation framework.
Browse files Browse the repository at this point in the history
  • Loading branch information
algernon-A committed Jan 23, 2022
1 parent 6124766 commit 73f96c1
Show file tree
Hide file tree
Showing 38 changed files with 1,573 additions and 1,539 deletions.
7 changes: 5 additions & 2 deletions Changelog.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
Version 1.6.0.3 hotfix
- Convert translation framework to CSV (for CrowdIn)

- Force JITter to not inline ResidentAI.UpdateWorkplace Prefix.

Version 1.6.0.3 hotfix

- Force JITter to not inline ResidentAI.UpdateWorkplace Prefix


Version 1.6.0.2 hotfix
Expand Down
2 changes: 1 addition & 1 deletion Code/Settings/ModSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public class ModSettings
/// Language code.
/// </summary>
[XmlElement("Language")]
public string XMLLanguage { get => Translations.Language; set => Translations.Language = value; }
public string XMLLanguage { get => Translations.CurrentLanguage; set => Translations.CurrentLanguage = value; }

/// <summary>
/// What's new notification version.
Expand Down
49 changes: 26 additions & 23 deletions Lifecycle Rebalance Revisited.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,22 @@
<None Include="LICENSE" />
<None Include="packages.config" />
<None Include="README.md" />
<None Include="Translations\en.csv" />
<None Include="Translations\pl.csv" />
<None Include="Translations\pt-br.csv" />
<None Include="Translations\ru.csv" />
<None Include="Translations\tr.csv" />
<None Include="Translations\zh-tw.csv" />
<None Include="Translations\zh.csv" />
<None Include="Translations\es.csv" />
<None Include="Translations\fi.csv" />
<None Include="Translations\fr.csv" />
<None Include="Translations\id.csv" />
<None Include="Translations\it.csv" />
<None Include="Translations\ja.csv" />
<None Include="Translations\kr.csv" />
<None Include="Translations\nl.csv" />
<None Include="Translations\de.csv" />
</ItemGroup>
<ItemGroup>
<Content Include="Help file.txt" />
Expand All @@ -103,22 +119,6 @@
<Content Include="Images\Screen_SampleRates.jpg" />
<Content Include="Images\Screen_SeniorMovedIn.jpg" />
<Content Include="Changelog.txt" />
<Content Include="Translations\de.xml" />
<Content Include="Translations\en.xml" />
<Content Include="Translations\es.xml" />
<Content Include="Translations\fi.xml" />
<Content Include="Translations\fr.xml" />
<Content Include="Translations\id.xml" />
<Content Include="Translations\it.xml" />
<Content Include="Translations\ja.xml" />
<Content Include="Translations\kr.xml" />
<Content Include="Translations\nl.xml" />
<Content Include="Translations\pl.xml" />
<Content Include="Translations\pt-br.xml" />
<Content Include="Translations\ru.xml" />
<Content Include="Translations\tr.xml" />
<Content Include="Translations\zh-tw.xml" />
<Content Include="Translations\zh.xml" />
<Content Include="XMLFileAndEditDiscussion.txt" />
<Content Include="XML_Files\WG_CarAsWealth.xml" />
<Content Include="XML_Files\WG_CarHeavy.xml" />
Expand Down Expand Up @@ -163,7 +163,7 @@
<Compile Include="Code\XML\XML_VerisonOne.cs" />
<Compile Include="Code\XML\XML_VersionTwo.cs" />
<Compile Include="TranslationFramework\TranslationFramework.cs" />
<Compile Include="TranslationFramework\TranslationXML.cs" />
<Compile Include="TranslationFramework\Language.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include=".git\objects\info\" />
Expand All @@ -177,9 +177,10 @@
<PropertyGroup>
<PostBuildEvent>mkdir "%25LOCALAPPDATA%25\Colossal Order\Cities_Skylines\Addons\Mods\$(ProjectName)"

del "%25LOCALAPPDATA%25\Colossal Order\Cities_Skylines\Addons\Mods\$(ProjectName)\$(TargetFileName)"
del "%25LOCALAPPDATA%25\Colossal Order\Cities_Skylines\Addons\Mods\$(ProjectName)\*.dll"

xcopy /y "$(TargetPath)" "%25LOCALAPPDATA%25\Colossal Order\Cities_Skylines\Addons\Mods\$(ProjectName)"


del "%25LOCALAPPDATA%25\Colossal Order\Cities_Skylines\Addons\Mods\$(ProjectName)\*.xml"

Expand All @@ -189,13 +190,15 @@ del "%25LOCALAPPDATA%25\Colossal Order\Cities_Skylines\Addons\Mods\$(ProjectName

xcopy /y "$(SolutionDir)\XMLFileAndEditDiscussion.txt" "%25LOCALAPPDATA%25\Colossal Order\Cities_Skylines\Addons\Mods\$(ProjectName)"

del "%25LOCALAPPDATA%25\Colossal Order\Cities_Skylines\Addons\Mods\$(ProjectName)\0Harmony.dll"
del "%25LOCALAPPDATA%25\Colossal Order\Cities_Skylines\Addons\Mods\$(ProjectName)\CitiesHarmony.API.dll"


xcopy /y "$(SolutionDir)packages\CitiesHarmony.API.2.0.0\lib\net35\CitiesHarmony.API.dll" "%25LOCALAPPDATA%25\Colossal Order\Cities_Skylines\Addons\Mods\$(ProjectName)"
xcopy /y "$(SolutionDir)packages\CitiesHarmony.API.2.0.0\lib\net35\CitiesHarmony.API.dll"
"%25LOCALAPPDATA%25\Colossal Order\Cities_Skylines\Addons\Mods\$(ProjectName)"

mkdir "%25LOCALAPPDATA%25\Colossal Order\Cities_Skylines\Addons\Mods\$(ProjectName)\Translations"
del "%25LOCALAPPDATA%25\Colossal Order\Cities_Skylines\Addons\Mods\$(ProjectName)\Translations\*.xml"

mkdir "%25LOCALAPPDATA%25\Colossal Order\Cities_Skylines\Addons\Mods\$(ProjectName)\Translations"

del "%25LOCALAPPDATA%25\Colossal Order\Cities_Skylines\Addons\Mods\$(ProjectName)\Translations\*.csv"

xcopy /y "$(SolutionDir)\Translations\" "$(LOCALAPPDATA)\Colossal Order\Cities_Skylines\Addons\Mods\$(ProjectName)\Translations" /s /e
</PostBuildEvent>
Expand Down
25 changes: 25 additions & 0 deletions TranslationFramework/Language.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System.Collections.Generic;


namespace LifecycleRebalance
{
/// <summary>
/// Translation language class.
/// </summary>
public class Language
{
// Translation file keywords - language code and readable name.
public static readonly string CodeKey = "CODE";
public static readonly string NameKey = "NAME";


// Dictionary of translations for this language.
public Dictionary<string, string> translationDictionary = new Dictionary<string, string>();

// Language unique name.
public string uniqueName = null;

// Language human-readable name.
public string readableName = null;
}
}
145 changes: 132 additions & 13 deletions TranslationFramework/TranslationFramework.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.Xml.Serialization;
using ColossalFramework;
using ColossalFramework.Globalization;

Expand All @@ -25,11 +24,11 @@ public static class Translations
/// <returns>Translation (or key if translation failed)</returns>
public static string Translate(string key) => Instance.Translate(key);

public static string Language
public static string CurrentLanguage
{
get
{
return Instance.Language;
return Instance.CurrentLanguage;
}
set
{
Expand Down Expand Up @@ -107,7 +106,7 @@ public class Translator
/// <summary>
/// Returns the current language code if one has specifically been set; otherwise, return "default".
/// </summary>
public string Language => currentIndex < 0 ? "default" : languages.Values[currentIndex].uniqueName;
public string CurrentLanguage => currentIndex < 0 ? "default" : languages.Values[currentIndex].uniqueName;


/// <summary>
Expand Down Expand Up @@ -348,7 +347,7 @@ private string FallbackTranslation(string attemptedLanguage, string key)


/// <summary>
/// Loads languages from XML files.
/// Loads languages from CSV files.
/// </summary>
private void LoadLanguages()
{
Expand All @@ -368,24 +367,144 @@ private void LoadLanguages()
string[] translationFiles = Directory.GetFiles(localePath);
foreach (string translationFile in translationFiles)
{
using (StreamReader reader = new StreamReader(translationFile))
// Skip anything that's not marked as a .csv file.
if (!translationFile.EndsWith(".csv"))
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Language));
if (xmlSerializer.Deserialize(reader) is Language translation)
continue;
}

// Read file.
FileStream fileStream = new FileStream(translationFile, FileMode.Open, FileAccess.Read);
using (StreamReader reader = new StreamReader(fileStream))
{
// Create new language instance for this file.
Language thisLanguage = new Language();
string key = null;
bool quoting = false;

// Iterate through each line of file.
string line = reader.ReadLine();
while (line != null)
{
// Are we parsing quoted lines?
if (quoting)
{
// Parsing a quoted line - make sure we have a valid current key.
if (!key.IsNullOrWhiteSpace())
{
// Yes - if the line ends with a quote, trim the quote and add to existing dictionary entry and stop quoting.
if (line.EndsWith("\""))
{
quoting = false;
thisLanguage.translationDictionary[key] += line.Substring(0, line.Length - 1);
}
else
{
// Line doesn't end with a quote - add line to existing dictionary entry and keep going.
thisLanguage.translationDictionary[key] += line + Environment.NewLine;
}
}
}
else
{
// Not parsing quoted line - look for comma separator on this line.
int commaPos = line.IndexOf(",");
if (commaPos > 0)
{
// Comma found - split line into key and value, delimited by first comma.
key = line.Substring(0, commaPos);
string value = line.Substring(commaPos + 1);

// Don't do anything if either key or value is invalid.
if (!key.IsNullOrWhiteSpace() && !value.IsNullOrWhiteSpace())
{
// Trim quotes off keys.
if (key.StartsWith("\""))
{
// Starts with quotation mark - if it also ends in a quotation mark, strip both quotation marks.
if (key.EndsWith("\""))
{
key = key.Substring(1, key.Length - 2);
}
else
{
// Doesn't end in a quotation mark, so just strip leading quotation mark.
key = key.Substring(1);
}
}

// Does this value start with a quotation mark?
if (value.StartsWith("\""))
{
// Starts with quotation mark - if it also ends in a quotation mark, strip both quotation marks.
if (value.EndsWith("\""))
{
value = value.Substring(1, value.Length - 2);
}
else
{
// Doesn't end in a quotation mark, so we've (presumably) got a multi-line quoted entry
// Flag quoting mode and set initial value to start of quoted string (less leading quotation mark), plus trailing newline.
quoting = true;
value = value.Substring(1) + Environment.NewLine;
}
}

// Check for reserved keywords.
if (key.Equals(Language.CodeKey))
{
// Language code.
thisLanguage.uniqueName = value;
}
else if (key.Equals(Language.NameKey))
{
// Language readable name.
thisLanguage.readableName = value;
}
else
{
// Try to add key/value pair to translation dictionary.
if (!thisLanguage.translationDictionary.ContainsKey(key))
{
thisLanguage.translationDictionary.Add(key, value);
}
else
{
Logging.Error("duplicate translation key ", key, " in file ", translationFile);
}
}
}
}
else
{
// No comma delimiter found - append to previous line (if last-used key is valid).
if (!key.IsNullOrWhiteSpace())
{
thisLanguage.translationDictionary[key] += line;
}
}
}

// Read next line.
line = reader.ReadLine();
}

// Did we get a valid dictionary from this?
if (thisLanguage.uniqueName != null && thisLanguage.readableName != null && thisLanguage.translationDictionary.Count > 0)
{
// Got one! add it to the list, if we don't already have a copy.
if (!languages.ContainsKey(translation.uniqueName))
// Yes - add to languages dictionary.
if (!languages.ContainsKey(thisLanguage.uniqueName))
{
languages.Add(translation.uniqueName, translation);
languages.Add(thisLanguage.uniqueName, thisLanguage);
}
else
{
Logging.Error("duplicate translation for ", translation.uniqueName);
Logging.Error("duplicate translation file for language ", thisLanguage.uniqueName);
}
}
else
{
Logging.Error("couldn't deserialize translation file '", translationFile);
Logging.Error("file ", translationFile, " did not produce a valid translation dictionary");
}
}
}
Expand Down
68 changes: 0 additions & 68 deletions TranslationFramework/TranslationXML.cs

This file was deleted.

Loading

0 comments on commit 73f96c1

Please sign in to comment.