2022-08-20 19:11:43 +00:00
using System ;
2020-12-22 03:13:18 +00:00
using System.Collections.Generic ;
2022-08-20 19:11:43 +00:00
using System.Reflection ;
2020-12-22 03:13:18 +00:00
2022-06-18 18:04:24 +00:00
namespace PKHeX.Core ;
2022-08-20 19:11:43 +00:00
/// <summary>
/// Localization utility for changing all properties of a static type.
/// </summary>
2022-06-18 18:04:24 +00:00
public static class LocalizationUtil
2020-12-22 03:13:18 +00:00
{
2022-06-18 18:04:24 +00:00
private const string TranslationSplitter = " = " ;
2022-08-20 19:11:43 +00:00
private const char TranslationFirst = ' ' ; // perf; no properties contain spaces.
2020-12-22 03:13:18 +00:00
2022-06-18 18:04:24 +00:00
/// <summary>
/// Gets the names of the properties defined in the given input
/// </summary>
/// <param name="input">Enumerable of translation definitions in the form "Property = Value".</param>
2022-08-20 19:11:43 +00:00
private static string [ ] GetProperties ( ReadOnlySpan < string > input )
2022-06-18 18:04:24 +00:00
{
2022-08-20 19:11:43 +00:00
var result = new string [ input . Length ] ;
for ( int i = 0 ; i < input . Length ; i + + )
2020-12-22 03:13:18 +00:00
{
2022-08-20 19:11:43 +00:00
var l = input [ i ] ;
var split = l . IndexOf ( TranslationFirst ) ;
result [ i ] = l [ . . split ] ;
2020-12-22 03:13:18 +00:00
}
2022-08-20 19:11:43 +00:00
return result ;
2022-06-18 18:04:24 +00:00
}
2022-08-20 19:11:43 +00:00
private static string [ ] DumpStrings ( Type t )
2022-06-18 18:04:24 +00:00
{
2022-08-20 19:11:43 +00:00
var ti = t . GetTypeInfo ( ) ;
var props = ( PropertyInfo [ ] ) ti . DeclaredProperties ;
var result = new string [ props . Length ] ;
for ( int i = 0 ; i < props . Length ; i + + )
{
var p = props [ i ] ;
var value = p . GetValue ( null ) ;
2022-11-25 04:06:46 +00:00
result [ i ] = $"{p.Name}{TranslationSplitter}{value}" ;
2022-08-20 19:11:43 +00:00
}
return result ;
2022-06-18 18:04:24 +00:00
}
2020-12-22 03:13:18 +00:00
2022-06-18 18:04:24 +00:00
/// <summary>
/// Gets the current localization in a static class containing language-specific strings
/// </summary>
/// <param name="t"></param>
2022-08-20 19:11:43 +00:00
public static string [ ] GetLocalization ( Type t ) = > DumpStrings ( t ) ;
2022-06-18 18:04:24 +00:00
/// <summary>
/// Gets the current localization in a static class containing language-specific strings
/// </summary>
/// <param name="t"></param>
/// <param name="existingLines">Existing localization lines (if provided)</param>
2022-08-20 19:11:43 +00:00
public static string [ ] GetLocalization ( Type t , ReadOnlySpan < string > existingLines )
2022-06-18 18:04:24 +00:00
{
var currentLines = GetLocalization ( t ) ;
var existing = GetProperties ( existingLines ) ;
var current = GetProperties ( currentLines ) ;
var result = new string [ currentLines . Length ] ;
for ( int i = 0 ; i < current . Length ; i + + )
2020-12-22 03:13:18 +00:00
{
2022-06-18 18:04:24 +00:00
int index = Array . IndexOf ( existing , current [ i ] ) ;
result [ i ] = index < 0 ? currentLines [ i ] : existingLines [ index ] ;
2020-12-22 03:13:18 +00:00
}
2022-06-18 18:04:24 +00:00
return result ;
}
2020-12-22 03:13:18 +00:00
2022-06-18 18:04:24 +00:00
/// <summary>
/// Applies localization to a static class containing language-specific strings.
/// </summary>
/// <param name="t">Type of the static class containing the desired strings.</param>
/// <param name="lines">Lines containing the localized strings</param>
2022-08-20 19:11:43 +00:00
private static void SetLocalization ( Type t , ReadOnlySpan < string > lines )
2022-06-18 18:04:24 +00:00
{
2022-08-20 19:11:43 +00:00
if ( lines . Length = = 0 )
2022-06-18 18:04:24 +00:00
return ;
2022-08-20 19:11:43 +00:00
var translatable = new Dictionary < string , string > ( lines . Length ) ;
2022-06-18 18:04:24 +00:00
foreach ( var line in lines )
2020-12-22 03:13:18 +00:00
{
2022-08-20 19:11:43 +00:00
var index = line . IndexOf ( TranslationFirst ) ;
2022-06-18 18:04:24 +00:00
if ( index < 0 )
continue ;
var prop = line [ . . index ] ;
2022-08-20 19:11:43 +00:00
translatable [ prop ] = line [ ( index + TranslationSplitter . Length ) . . ] ;
}
2020-12-22 03:13:18 +00:00
2022-08-20 19:11:43 +00:00
var ti = t . GetTypeInfo ( ) ;
var props = ( PropertyInfo [ ] ) ti . DeclaredProperties ;
foreach ( var p in props )
{
if ( translatable . TryGetValue ( p . Name , out var value ) )
p . SetValue ( null , value ) ;
2020-12-22 03:13:18 +00:00
}
2022-06-18 18:04:24 +00:00
}
2020-12-22 03:13:18 +00:00
2022-06-18 18:04:24 +00:00
/// <summary>
/// Applies localization to a static class containing language-specific strings.
/// </summary>
/// <param name="t">Type of the static class containing the desired strings.</param>
/// <param name="languageFilePrefix">Prefix of the language file to use. Example: if the target is legality_en.txt, <paramref name="languageFilePrefix"/> should be "legality".</param>
/// <param name="currentCultureCode">Culture information</param>
private static void SetLocalization ( Type t , string languageFilePrefix , string currentCultureCode )
{
var lines = Util . GetStringList ( $"{languageFilePrefix}_{currentCultureCode}" ) ;
SetLocalization ( t , lines ) ;
}
2020-12-22 03:13:18 +00:00
2022-06-18 18:04:24 +00:00
/// <summary>
/// Applies localization to a static class containing language-specific strings.
/// </summary>
/// <param name="t">Type of the static class containing the desired strings.</param>
/// <remarks>The values used to translate the given static class are retrieved from [TypeName]_[CurrentLangCode2].txt in the resource manager of PKHeX.Core.</remarks>
/// <param name="currentCultureCode">Culture information</param>
public static void SetLocalization ( Type t , string currentCultureCode )
{
SetLocalization ( t , t . Name , currentCultureCode ) ;
2020-12-22 03:13:18 +00:00
}
}