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 ); }