Has anyone gotten a working system for localization using C#? Today I ran into the issue that C# isn’t supported using Godot’s localization system. However I ended up finding GetText.NET. This seemed to work out well, I was able to start replacing my strings with it and generating locale .po files. But later ran into the issue that Godot exported builds don’t seem to have any way to include my Local/**/*.mo files in the build.
While this is a minor issue, I was wondering if anyone has found a better solution? Since with my current setup I need to write some tooling to export unzipped, copy the locale files over and then zip it myself.
I found out you can use FileAccess to read bundled .mo files which will be bundled if you add them as translation files in the project settings.
GetText.NET does support reading a stream, so I attempted creating a stream wrapper, however when attempting to load the bundled resource it seems GetText.NET reads empty bytes, while my read function is getting the correct data.
EDIT:
This now works and doesn’t have the above problems I mentioned.
GodotReousrceStream
using System.IO;
using FileAccess = Godot.FileAccess;
public class GodotResourceStream(string resPath) : Stream
{
private readonly FileAccess _file = FileAccess.Open(resPath, FileAccess.ModeFlags.ReadWrite);
public override void Flush() => _file.Flush();
public override int Read(byte[] buffer, int offset, int count)
{
var temp = _file.GetBuffer(count);
temp.CopyTo(buffer, offset);
return temp.Length;
}
public override long Seek(long offset, SeekOrigin origin)
{
switch (origin)
{
case SeekOrigin.Begin:
_file.Seek((ulong)offset);
break;
case SeekOrigin.Current:
_file.Seek(_file.GetPosition() + (ulong)offset);
break;
case SeekOrigin.End:
_file.SeekEnd(offset);
break;
}
return (long)_file.GetPosition();
}
public override void SetLength(long value) => _file.Resize(value);
public override void Write(byte[] buffer, int offset, int count)
{
_file.Seek((ulong)offset);
_file.StoreBuffer(buffer);
}
public override bool CanRead => true;
public override bool CanSeek => true;
public override bool CanWrite => true;
public override long Length => (long)_file.GetLength();
public override long Position
{
get => (long)_file.GetPosition();
set => _file.Seek((ulong)value);
}
}
The -as Translate there is the important part because if you’re using Godot’s translation server this is what will flag it to look for calls to a Translate method and add them to the .pot file.
This is much less complex and doesn’t require a stream wrapper or managing the translations yourself.
So I started finding it annoying that I was generating 2 separate POT files one for in-editor using Godot’s tools and one outside from C# code. I found out it’s pretty simple to write an extension plugin, so I did just that and now I can add .cs files to Godot’s translation file list.
It’s extremely rudimentary, it’s just doing a regex search for Translate("...") but it gets the job done.