namespace Sandbox;
///
/// A container for the current language, allowing access to translated phrases and language information.
///
public class LanguageContainer
{
///
/// The abbreviation for the language the user wants. This is set by the user in the options menu.
///
public string SelectedCode => Application.LanguageCode;
///
/// Information about the current selected language. Will default to English if the current language isn't found.
///
public Sandbox.Localization.LanguageInformation Current { get; internal set; }
Sandbox.Localization.PhraseCollection lang;
BaseFileSystem filesystem;
FileWatch _watcher;
internal LanguageContainer( BaseFileSystem filesystem )
{
this.filesystem = filesystem;
Tick();
_watcher = filesystem.Watch();
_watcher.OnChanges += x => OnFileChanged();
}
string _previousLanguage;
internal void Tick()
{
var language = Application.LanguageCode;
language ??= "en";
language = language.ToLower();
if ( _previousLanguage == language )
return;
_previousLanguage = language;
// Add english first for fallbacks
lang = new Localization.PhraseCollection();
AddFromPath( "en" );
// Switch to new language
AddFromPath( language );
}
void AddFromPath( string shortName )
{
if ( string.IsNullOrWhiteSpace( shortName ) ) return;
if ( shortName.Contains( "." ) ) return;
if ( shortName.Contains( ":" ) ) return;
if ( shortName.Contains( "/" ) ) return;
var language = Sandbox.Localization.Languages.Find( shortName );
if ( language != null ) Current = language;
foreach ( var file in filesystem.FindFile( shortName, "*.json" ) )
{
AddFile( $"{shortName}/{file}" );
}
}
void AddFile( string path )
{
try
{
var entries = filesystem.ReadJson>( path );
if ( entries == null ) return;
foreach ( var entry in entries )
{
lang.Set( entry.Key, entry.Value );
}
}
catch ( Exception e )
{
Log.Warning( $"Couldn't read localization file {path}: {e}" );
}
}
///
/// Called when a localization file has changed (and we should reload)
///
internal void OnFileChanged()
{
// setting this to null will cause a reload in tick
_previousLanguage = null;
}
///
/// Look up a phrase
///
/// The token used to identify the phrase
/// Key values of data used by the string. Example: {Variable} -> { "Variable", someVar }
/// If found will return the phrase, else will return the token itself
public string GetPhrase( string textToken, Dictionary data = null )
{
if ( lang == null ) return textToken;
return lang.GetPhrase( textToken, data );
}
internal void Shutdown()
{
_watcher?.Dispose();
_watcher = null;
filesystem?.Dispose();
filesystem = null;
}
}
///
/// Allows access to translated phrases, allowing the translation of gamemodes etc
///
[SkipHotload]
public static class Language
{
///
/// The abbreviation for the language the user wants. This is set by the user in the options menu.
///
public static string SelectedCode => Game.Language.SelectedCode;
///
/// Information about the current selected language. Will default to English if the current language isn't found.
///
public static Sandbox.Localization.LanguageInformation Current => Game.Language.Current;
///
/// Look up a phrase
///
/// The token used to identify the phrase
/// Key values of data used by the string. Example: {Variable} -> { "Variable", someVar }
/// If found will return the phrase, else will return the token itself
public static string GetPhrase( string textToken, Dictionary data = null ) => Game.Language.GetPhrase( textToken, data );
}