2021-06-01 10:49:37 +00:00
using System ;
2021-05-20 15:11:43 +00:00
using System.Collections.Generic ;
2021-11-29 12:53:46 +00:00
using System.Diagnostics ;
2021-05-20 15:11:43 +00:00
using System.IO ;
using System.Linq ;
using System.Text.RegularExpressions ;
2021-05-31 15:34:15 +00:00
using Newtonsoft.Json ;
2021-05-20 15:11:43 +00:00
using Newtonsoft.Json.Linq ;
using NUnit.Framework ;
namespace Frontend.Translations.Tests
{
public class Tests
{
public static string BasePath
{
get
{
return "..\\..\\..\\..\\..\\..\\" ;
}
}
public List < string > Workspaces { get ; set ; }
public List < TranslationFile > TranslationFiles { get ; set ; }
public List < JavaScriptFile > JavaScriptFiles { get ; set ; }
2021-05-27 12:51:44 +00:00
public List < ModuleFolder > ModuleFolders { get ; set ; }
2021-06-01 17:00:36 +00:00
public List < KeyValuePair < string , string > > NotTranslatedToasts { get ; set ; }
2021-05-28 07:58:27 +00:00
public List < LanguageItem > CommonTranslations { get ; set ; }
2021-11-29 12:53:46 +00:00
public List < ParseJsonError > ParseJsonErrors { get ; set ; }
2021-05-28 07:58:27 +00:00
2021-11-29 12:53:46 +00:00
[OneTimeSetUp]
2021-05-20 15:11:43 +00:00
public void Setup ( )
{
2021-11-29 12:53:46 +00:00
ParseJsonErrors = new List < ParseJsonError > ( ) ;
2021-05-20 15:11:43 +00:00
var packageJsonPath = Path . Combine ( BasePath , @"package.json" ) ;
2021-05-28 07:58:27 +00:00
2021-05-20 15:11:43 +00:00
var jsonPackage = JObject . Parse ( File . ReadAllText ( packageJsonPath ) ) ;
2021-06-01 17:00:36 +00:00
var moduleWorkspaces = ( ( JArray ) jsonPackage [ "workspaces" ] )
. Select ( p = > ( ( string ) p ) . Replace ( "/" , "\\" ) )
. Where ( w = > ! w . Contains ( "asc-web-components" ) )
. ToList ( ) ;
2021-05-27 12:51:44 +00:00
Workspaces = new List < string > ( ) ;
Workspaces . AddRange ( moduleWorkspaces ) ;
2021-05-20 15:11:43 +00:00
Workspaces . Add ( "public\\locales" ) ;
var translationFiles = from wsPath in Workspaces
let clientDir = Path . Combine ( BasePath , wsPath )
from file in Directory . EnumerateFiles ( clientDir , "*.json" , SearchOption . AllDirectories )
where file . Contains ( "public\\locales\\" )
select file ;
TranslationFiles = new List < TranslationFile > ( ) ;
foreach ( var path in translationFiles )
{
2021-11-29 12:53:46 +00:00
try
{
var jsonTranslation = JObject . Parse ( File . ReadAllText ( path ) ) ;
2021-05-20 15:11:43 +00:00
2021-11-29 12:53:46 +00:00
var translationFile = new TranslationFile ( path , jsonTranslation . Properties ( )
. Select ( p = > new TranslationItem ( p . Name , ( string ) p . Value ) )
. ToList ( ) ) ;
2021-05-20 15:11:43 +00:00
2021-11-29 12:53:46 +00:00
TranslationFiles . Add ( translationFile ) ;
2021-05-31 15:34:15 +00:00
2021-11-29 12:53:46 +00:00
/* Re-write by order */
2021-05-31 15:34:15 +00:00
2021-11-29 12:53:46 +00:00
//var orderedList = jsonTranslation.Properties().OrderBy(t => t.Name);
2021-05-31 15:34:15 +00:00
2021-11-29 12:53:46 +00:00
//var result = new JObject(orderedList);
2021-05-31 15:34:15 +00:00
2021-11-29 12:53:46 +00:00
//var sortedJsonString = JsonConvert.SerializeObject(result, Formatting.Indented);
2021-05-31 15:34:15 +00:00
2021-11-29 12:53:46 +00:00
//File.WriteAllText(path, sortedJsonString);
}
catch ( Exception ex )
{
ParseJsonErrors . Add ( new ParseJsonError ( path , ex ) ) ;
Debug . WriteLine ( $"File path = {path} failed to parse with error: {ex.Message}" ) ;
}
2021-05-20 15:11:43 +00:00
}
var javascriptFiles = ( from wsPath in Workspaces
let clientDir = Path . Combine ( BasePath , wsPath )
from file in Directory . EnumerateFiles ( clientDir , "*.js" , SearchOption . AllDirectories )
2021-05-21 12:39:49 +00:00
where ! file . Contains ( "dist\\" )
2021-05-20 15:11:43 +00:00
select file )
. ToList ( ) ;
javascriptFiles . AddRange ( from wsPath in Workspaces
let clientDir = Path . Combine ( BasePath , wsPath )
from file in Directory . EnumerateFiles ( clientDir , "*.jsx" , SearchOption . AllDirectories )
2021-05-21 12:39:49 +00:00
where ! file . Contains ( "dist\\" )
2021-05-20 15:11:43 +00:00
select file ) ;
JavaScriptFiles = new List < JavaScriptFile > ( ) ;
2021-05-21 11:38:11 +00:00
var pattern1 = "[.{\\s\\(]t\\(\\s*[\"\'`]([a-zA-Z0-9_.:_\\s{}/_-]+)[\"\'`]\\s*[\\),]" ;
2021-05-20 15:11:43 +00:00
var pattern2 = "i18nKey=\"([a-zA-Z0-9_.-]+)\"" ;
var regexp = new Regex ( $"({pattern1})|({pattern2})" , RegexOptions . Multiline | RegexOptions . ECMAScript ) ;
2021-06-01 17:00:36 +00:00
var notTranslatedToastsRegex = new Regex ( "(?<=toastr.info\\([\"`\'])(.*)(?=[\"\'`])" +
"|(?<=toastr.error\\([\"`\'])(.*)(?=[\"\'`])" +
"|(?<=toastr.success\\([\"`\'])(.*)(?=[\"\'`])" +
"|(?<=toastr.warn\\([\"`\'])(.*)(?=[\"\'`])" , RegexOptions . Multiline | RegexOptions . ECMAScript ) ;
NotTranslatedToasts = new List < KeyValuePair < string , string > > ( ) ;
2021-05-20 15:11:43 +00:00
foreach ( var path in javascriptFiles )
{
var jsFileText = File . ReadAllText ( path ) ;
2021-06-01 17:00:36 +00:00
var toastMatches = notTranslatedToastsRegex . Matches ( jsFileText ) . ToList ( ) ;
if ( toastMatches . Any ( ) )
{
foreach ( var toastMatch in toastMatches )
{
var found = toastMatch . Value ;
if ( ! string . IsNullOrEmpty ( found ) & & ! NotTranslatedToasts . Exists ( t = > t . Value = = found ) )
NotTranslatedToasts . Add ( new KeyValuePair < string , string > ( path , found ) ) ;
}
}
2021-05-20 15:11:43 +00:00
var matches = regexp . Matches ( jsFileText ) ;
2021-05-21 12:27:56 +00:00
var translationKeys = matches
. Select ( m = > m . Groups [ 2 ] . Value = = ""
? m . Groups [ 4 ] . Value
: m . Groups [ 2 ] . Value )
. ToList ( ) ;
2021-05-20 15:11:43 +00:00
if ( ! translationKeys . Any ( ) )
continue ;
var jsFile = new JavaScriptFile ( path ) ;
jsFile . TranslationKeys = translationKeys ;
JavaScriptFiles . Add ( jsFile ) ;
}
2021-05-27 12:51:44 +00:00
ModuleFolders = new List < ModuleFolder > ( ) ;
var list = TranslationFiles
. Select ( t = > new
{
2021-06-01 08:29:46 +00:00
ModulePath = moduleWorkspaces . FirstOrDefault ( m = > t . FilePath . Contains ( m ) ) ,
2021-05-27 12:51:44 +00:00
Language = new LanguageItem
{
2021-06-01 08:29:46 +00:00
Path = t . FilePath ,
2021-05-27 12:51:44 +00:00
Language = t . Language ,
Translations = t . Translations
} ,
lng = t . Language
} ) . ToList ( ) ;
var moduleTranslations = list
. GroupBy ( t = > t . ModulePath )
. Select ( g = > new
{
ModulePath = g . Key ,
Languages = g . ToList ( ) . Select ( t = > t . Language ) . ToList ( )
. ToList ( )
} )
. ToList ( ) ;
var moduleJsTranslatedFiles = JavaScriptFiles
. Select ( t = > new
{
ModulePath = moduleWorkspaces . FirstOrDefault ( m = > t . Path . Contains ( m ) ) ,
t . Path ,
t . TranslationKeys
} )
. GroupBy ( t = > t . ModulePath )
. Select ( g = > new
{
ModulePath = g . Key ,
TranslationKeys = g . ToList ( ) . SelectMany ( t = > t . TranslationKeys ) . ToList ( )
} )
. ToList ( ) ;
foreach ( var ws in moduleWorkspaces )
{
var t = moduleTranslations . FirstOrDefault ( t = > t . ModulePath = = ws ) ;
var j = moduleJsTranslatedFiles . FirstOrDefault ( t = > t . ModulePath = = ws ) ;
if ( j = = null & & t = = null )
continue ;
ModuleFolders . Add ( new ModuleFolder
{
Path = ws ,
AvailableLanguages = t ? . Languages ,
AppliedJsTranslationKeys = j ? . TranslationKeys
} ) ;
}
2021-05-28 07:58:27 +00:00
CommonTranslations = TranslationFiles
2021-06-01 08:29:46 +00:00
. Where ( file = > file . FilePath . StartsWith ( $"{BasePath}public\\locales" ) )
2021-05-28 07:58:27 +00:00
. Select ( t = > new LanguageItem
{
2021-06-01 08:29:46 +00:00
Path = t . FilePath ,
2021-05-28 07:58:27 +00:00
Language = t . Language ,
Translations = t . Translations
} ) . ToList ( ) ;
2021-05-20 15:11:43 +00:00
}
2021-11-29 12:53:46 +00:00
[Test]
public void ParseJsonTest ( )
{
Assert . AreEqual ( 0 , ParseJsonErrors . Count , string . Join ( "\r\n" , ParseJsonErrors . Select ( e = > $"File path = '{e.Path}' failed to parse with error: '{e.Exception.Message}'" ) ) ) ;
}
2021-05-25 14:19:05 +00:00
[Test]
public void FullDublicatesTest ( )
{
var fullEnDuplicates = TranslationFiles
. Where ( file = > file . Language = = "en" )
. SelectMany ( item = > item . Translations )
. GroupBy ( t = > new { t . Key , t . Value } )
. Where ( grp = > grp . Count ( ) > 1 )
. Select ( grp = > new { Key = grp . Key , Count = grp . Count ( ) , Keys = grp . ToList ( ) } )
. OrderByDescending ( itm = > itm . Count )
. Select ( grp = > new { Key = grp . Key . Key , Value = grp . Key . Value , grp . Count } )
. ToList ( ) ;
Assert . AreEqual ( 0 , fullEnDuplicates . Count , string . Join ( "\r\n" , fullEnDuplicates . Select ( d = > JObject . FromObject ( d ) . ToString ( ) ) ) ) ;
}
2021-05-20 15:11:43 +00:00
[Test]
public void DublicatesByContentTest ( )
{
2021-05-25 14:19:05 +00:00
var allRuTranslations = TranslationFiles
. Where ( file = > file . Language = = "ru" )
. SelectMany ( item = > item . Translations )
. ToList ( ) ;
var allEnDuplicates = TranslationFiles
. Where ( file = > file . Language = = "en" )
2021-05-20 15:11:43 +00:00
. SelectMany ( item = > item . Translations )
. GroupBy ( t = > t . Value )
2021-05-21 08:05:37 +00:00
. Where ( grp = > grp . Count ( ) > 1 )
2021-05-25 14:19:05 +00:00
. Select ( grp = > new { ContentKey = grp . Key , Count = grp . Count ( ) , List = grp . ToList ( ) } )
2021-05-20 15:11:43 +00:00
. OrderByDescending ( itm = > itm . Count )
. ToList ( ) ;
2021-05-25 14:19:05 +00:00
var duplicatesKeys = new List < TranslationItem > ( ) ;
foreach ( var item in allEnDuplicates )
{
var ruEquivalents = allRuTranslations
. Where ( t = > item . List . Select ( k = > k . Key ) . Contains ( t . Key ) )
. GroupBy ( t = > t . Value )
. Select ( grp = > new
{
ContentKey = grp . Key ,
Count = grp . Count ( ) ,
Keys = grp . Select ( k = > k . Key ) . ToList ( )
} )
. Where ( t = > t . Count > 1 )
. ToList ( ) ;
if ( ! ruEquivalents . Any ( ) )
continue ;
duplicatesKeys . AddRange (
item . List . Where ( item = > ruEquivalents
. SelectMany ( k = > k . Keys )
. Any ( k = > k = = item . Key )
)
) ;
}
var duplicates = duplicatesKeys
. GroupBy ( k = > k . Value )
. Select ( g = > new { ContentKey = g . Key , Count = g . Count ( ) , Keys = g . ToList ( ) } )
. ToList ( ) ;
Assert . AreEqual ( 0 , duplicates . Count , string . Join ( ", " , duplicates . Select ( d = > JObject . FromObject ( d ) . ToString ( ) ) ) ) ;
2021-05-20 15:11:43 +00:00
}
2021-05-31 17:33:12 +00:00
public static void SaveNotFoundLanguage ( string existJsonPath , string notExistJsonPath )
2021-05-31 16:11:58 +00:00
{
if ( ! File . Exists ( existJsonPath ) | | File . Exists ( notExistJsonPath ) )
return ;
var jsonTranslation = JObject . Parse ( File . ReadAllText ( existJsonPath ) ) ;
var properties = jsonTranslation . Properties ( ) . Select ( t = > t ) . ToList ( ) ;
properties . ForEach ( p = > p . Value = "" ) ;
var result = new JObject ( properties ) ;
var sortedJsonString = JsonConvert . SerializeObject ( result , Formatting . Indented ) ;
string currentDirectory = Path . GetDirectoryName ( notExistJsonPath ) ;
string fullPathOnly = Path . GetFullPath ( currentDirectory ) ;
if ( ! Directory . Exists ( fullPathOnly ) )
Directory . CreateDirectory ( fullPathOnly ) ;
File . WriteAllText ( notExistJsonPath , sortedJsonString ) ;
}
2021-05-20 15:11:43 +00:00
[Test]
public void NotAllLanguageTranslatedTest ( )
{
var groupedByLng = TranslationFiles
. GroupBy ( t = > t . Language )
2021-05-27 09:15:45 +00:00
. Select ( grp = > new { Lng = grp . Key , Count = grp . Count ( ) , Files = grp . ToList ( ) } )
2021-05-20 15:11:43 +00:00
. ToList ( ) ;
2021-06-01 08:29:46 +00:00
// Uncomment if new language is needed
//var newLng = "sk";
//if (!groupedByLng.Exists(t => t.Lng == newLng))
// groupedByLng.Add(new { Lng = newLng, Count = 0, Files = new List<TranslationFile>() });
2021-05-20 15:11:43 +00:00
var enGroup = groupedByLng . Find ( f = > f . Lng = = "en" ) ;
2021-05-21 12:27:56 +00:00
var expectedCount = enGroup . Count ;
2021-05-20 15:11:43 +00:00
2021-05-21 12:27:56 +00:00
var otherLngs = groupedByLng . Where ( g = > g . Lng ! = "en" ) ;
var incompleteList = otherLngs
. Where ( lng = > lng . Count ! = expectedCount )
2021-05-27 09:15:45 +00:00
. Select ( lng = > new { Issue = $"Language '{lng.Lng}' (Count={lng.Count}). Not found files:\r\n" , lng . Lng , lng . Files } )
2021-05-21 12:27:56 +00:00
. ToList ( ) ;
2021-05-27 09:15:45 +00:00
var message = $"Next languages are not equal 'en' (Count= {expectedCount}) by translated files count:\r\n\r\n" ;
if ( incompleteList . Count > 0 )
{
2021-06-01 08:29:46 +00:00
var enFilePaths = enGroup . Files . Select ( f = > f . FilePath ) ;
2021-05-27 09:15:45 +00:00
for ( int i = 0 ; i < incompleteList . Count ; i + + )
{
var lng = incompleteList [ i ] ;
2021-12-03 09:15:21 +00:00
message + = $"\r\n\r\n{i}. {lng.Issue}\r\n" ;
2021-05-27 09:15:45 +00:00
2021-06-01 08:29:46 +00:00
var lngFilePaths = lng . Files . Select ( f = > f . FilePath ) . ToList ( ) ;
2021-05-27 09:15:45 +00:00
var notFoundFilePaths = enFilePaths
. Select ( p = > p . Replace ( "\\en\\" , $"\\{lng.Lng}\\" ) )
. Where ( p = > ! lngFilePaths . Contains ( p ) ) ;
message + = string . Join ( "\r\n" , notFoundFilePaths ) ;
2021-05-31 16:11:58 +00:00
/* Save empty 'EN' keys to not found files */
2021-06-11 15:18:38 +00:00
/ * foreach ( var path in notFoundFilePaths )
2021-06-01 08:29:46 +00:00
{
SaveNotFoundLanguage ( path . Replace ( $"\\{lng.Lng}\\" , "\\en\\" ) , path ) ;
2021-06-11 15:18:38 +00:00
} * /
2021-05-27 09:15:45 +00:00
}
}
Assert . AreEqual ( 0 , incompleteList . Count , message ) ;
2021-05-20 15:11:43 +00:00
}
2021-05-31 17:33:12 +00:00
public static void SaveNotFoundKeys ( string pathToJson , List < string > newKeys )
2021-05-20 15:11:43 +00:00
{
2021-05-31 17:33:12 +00:00
if ( ! File . Exists ( pathToJson ) )
return ;
2021-05-20 15:11:43 +00:00
2021-05-31 17:33:12 +00:00
var jsonTranslation = JObject . Parse ( File . ReadAllText ( pathToJson ) ) ;
2021-05-20 15:11:43 +00:00
2021-05-31 17:33:12 +00:00
var properties = jsonTranslation . Properties ( ) . Select ( t = > t ) . ToList ( ) ;
2021-05-20 15:11:43 +00:00
2021-05-31 18:01:47 +00:00
properties . AddRange ( newKeys . Select ( k = > new JProperty ( k , "" ) ) ) ;
2021-05-21 12:27:56 +00:00
2021-05-31 17:33:12 +00:00
properties = properties . OrderBy ( t = > t . Name ) . ToList ( ) ;
2021-05-21 12:27:56 +00:00
2021-05-31 17:33:12 +00:00
var result = new JObject ( properties ) ;
2021-05-27 13:37:38 +00:00
2021-05-31 17:33:12 +00:00
var sortedJsonString = JsonConvert . SerializeObject ( result , Formatting . Indented ) ;
File . WriteAllText ( pathToJson , sortedJsonString ) ;
}
[Test]
public void NotTranslatedKeysTest ( )
{
var message = $"Next languages are not equal 'en' by translated keys count:\r\n\r\n" ;
var exists = false ;
var i = 0 ;
foreach ( var module in ModuleFolders )
2021-05-27 13:37:38 +00:00
{
2021-05-31 17:33:12 +00:00
if ( module . AvailableLanguages = = null )
continue ;
2021-05-27 13:37:38 +00:00
2021-05-31 17:33:12 +00:00
var enLanguages = module . AvailableLanguages . Where ( l = > l . Language = = "en" ) . ToList ( ) ;
var otherLanguages = module . AvailableLanguages . Where ( l = > l . Language ! = "en" ) . ToList ( ) ;
foreach ( var lng in otherLanguages )
2021-05-27 13:37:38 +00:00
{
2021-05-31 17:33:12 +00:00
var lngKeys = lng . Translations . Select ( f = > f . Key ) . ToList ( ) ;
2021-05-27 13:37:38 +00:00
2021-05-31 17:33:12 +00:00
var enKeys = enLanguages . Where ( l = > l . Path = = lng . Path . Replace ( $"\\{lng.Language}\\" , "\\en\\" ) )
. SelectMany ( l = > l . Translations . Select ( f = > f . Key ) )
. ToList ( ) ;
2021-05-27 13:37:38 +00:00
2021-05-31 17:33:12 +00:00
var notFoundKeys = enKeys . Except ( lngKeys ) . ToList ( ) ;
2021-05-27 13:37:38 +00:00
2021-05-31 17:33:12 +00:00
if ( ! notFoundKeys . Any ( ) )
continue ;
exists = true ;
message + = $"{++i}. Language ('{lng.Language}'={notFoundKeys.Count}/'en'={enKeys.Count}). Path '{lng.Path}' " +
$"Not found keys:\r\n\r\n" ;
2021-05-27 13:37:38 +00:00
message + = string . Join ( "\r\n" , notFoundKeys ) + "\r\n\r\n" ;
2021-05-31 17:33:12 +00:00
// Save empty not found keys
//SaveNotFoundKeys(lng.Path, notFoundKeys);
2021-05-27 13:37:38 +00:00
}
}
2021-05-31 17:33:12 +00:00
Assert . AreEqual ( false , exists , message ) ;
2021-05-20 15:11:43 +00:00
}
[Test]
public void NotFoundKeysTest ( )
{
var allEnKeys = TranslationFiles
2021-05-25 14:19:05 +00:00
. Where ( file = > file . Language = = "en" )
2021-05-20 15:11:43 +00:00
. SelectMany ( item = > item . Translations )
. Select ( item = > item . Key ) ;
var allJsTranslationKeys = JavaScriptFiles
2021-11-08 12:46:15 +00:00
. Where ( f = > ! f . Path . Contains ( "Banner.js" ) ) // skip Banner.js (translations from firebase)
2021-05-20 15:11:43 +00:00
. SelectMany ( j = > j . TranslationKeys )
2021-11-22 08:19:52 +00:00
. Select ( k = > k . Substring ( k . IndexOf ( ":" ) + 1 ) )
2021-05-20 15:11:43 +00:00
. Distinct ( ) ;
var notFoundJsKeys = allJsTranslationKeys . Except ( allEnKeys ) ;
2021-05-21 12:27:56 +00:00
Assert . AreEqual ( 0 , notFoundJsKeys . Count ( ) ,
"Some i18n-keys are not exist in translations in 'en' language: Keys: '{0}'" ,
2021-05-25 14:19:05 +00:00
string . Join ( "\r\n" , notFoundJsKeys ) ) ;
2021-05-20 15:11:43 +00:00
}
2021-05-21 10:34:35 +00:00
[Test]
public void UselessTranslationKeysTest ( )
{
var allEnKeys = TranslationFiles
2021-05-25 14:19:05 +00:00
. Where ( file = > file . Language = = "en" )
2021-05-21 10:34:35 +00:00
. SelectMany ( item = > item . Translations )
. Select ( item = > item . Key )
. Where ( k = > ! k . StartsWith ( "Culture_" ) ) ;
var allJsTranslationKeys = JavaScriptFiles
. SelectMany ( j = > j . TranslationKeys )
2021-11-22 08:19:52 +00:00
. Select ( k = > k . Substring ( k . IndexOf ( ":" ) + 1 ) )
2021-05-21 10:34:35 +00:00
. Where ( k = > ! k . StartsWith ( "Culture_" ) )
. Distinct ( ) ;
var notFoundi18nKeys = allEnKeys . Except ( allJsTranslationKeys ) ;
2021-05-21 12:27:56 +00:00
Assert . AreEqual ( 0 , notFoundi18nKeys . Count ( ) ,
2021-05-26 07:50:14 +00:00
"Some i18n-keys are not found in js: \r\nKeys: '\r\n{0}'" ,
2021-05-25 14:19:05 +00:00
string . Join ( "\r\n" , notFoundi18nKeys ) ) ;
2021-05-21 10:34:35 +00:00
}
2021-05-28 07:58:27 +00:00
[Test]
public void UselessModuleTranslationKeysTest ( )
{
var notFoundi18nKeys = new List < KeyValuePair < string , List < string > > > ( ) ;
var message = $"Some i18n-keys are not found in js: \r\nKeys: \r\n\r\n" ;
for ( int i = 0 ; i < ModuleFolders . Count ; i + + )
{
var module = ModuleFolders [ i ] ;
if ( module . AppliedJsTranslationKeys = = null & & module . AvailableLanguages ! = null )
{
message + = $"{i}. 'ANY LANGUAGES' '{module.Path}' NOT USES" ;
var list = module . AvailableLanguages
. SelectMany ( l = > l . Translations . Select ( t = > t . Key ) . ToList ( ) )
. ToList ( ) ;
notFoundi18nKeys . Add ( new KeyValuePair < string , List < string > > ( "ANY LANGUAGES" , list ) ) ;
continue ;
}
var notCommonKeys = module . AppliedJsTranslationKeys
. Where ( k = > ! k . StartsWith ( "Common:" ) )
. ToList ( ) ;
var onlyCommonKeys = module . AppliedJsTranslationKeys
. Except ( notCommonKeys )
. Select ( k = > k . Replace ( "Common:" , "" ) )
. ToList ( ) ;
if ( onlyCommonKeys . Any ( ) )
{
foreach ( var lng in CommonTranslations )
{
var list = onlyCommonKeys
. Except ( lng . Translations . Select ( t = > t . Key ) )
. ToList ( ) ;
if ( ! list . Any ( ) )
continue ;
message + = $"{i}. '{lng.Language}' '{module.Path}' \r\n {string.Join(" \ r \ n ", list)} \r\n" ;
notFoundi18nKeys . Add ( new KeyValuePair < string , List < string > > ( lng . Language , list ) ) ;
}
}
if ( module . AvailableLanguages = = null )
{
if ( notCommonKeys . Any ( ) )
{
message + = $"{i}. 'ANY LANGUAGES' '{module.Path}' \r\n {string.Join(" \ r \ n ", notCommonKeys)} \r\n" ;
notFoundi18nKeys . Add ( new KeyValuePair < string , List < string > > ( "ANY LANGUAGES" , notCommonKeys ) ) ;
}
continue ;
}
foreach ( var lng in module . AvailableLanguages )
{
var list = lng . Translations
2021-05-28 08:35:55 +00:00
. Select ( t = > t . Key )
2021-11-22 11:58:06 +00:00
. Except ( notCommonKeys . Select ( k = > k . Substring ( k . IndexOf ( ":" ) + 1 ) ) )
2021-05-28 07:58:27 +00:00
. ToList ( ) ;
if ( ! list . Any ( ) )
continue ;
message + = $"{i}. '{lng.Language}' '{module.Path}' \r\n {string.Join(" \ r \ n ", list)} \r\n" ;
notFoundi18nKeys . Add ( new KeyValuePair < string , List < string > > ( lng . Language , list ) ) ;
}
}
2021-06-01 08:29:46 +00:00
Assert . AreEqual ( 0 , notFoundi18nKeys . Count , message ) ;
2021-05-28 07:58:27 +00:00
}
2021-05-28 08:49:05 +00:00
[Test]
public void NotTranslatedCommonKeysTest ( )
{
var message = $"Some i18n-keys are not found in COMMON translations: \r\nKeys: \r\n\r\n" ;
var enLanguageKeys = CommonTranslations
. Where ( l = > l . Language = = "en" )
. FirstOrDefault ( )
. Translations
. Select ( k = > k . Key )
. ToList ( ) ;
var otherCommonLanguages = CommonTranslations . Where ( l = > l . Language ! = "en" ) ;
2021-06-01 14:00:55 +00:00
var exists = false ;
2021-05-28 08:49:05 +00:00
var i = 0 ;
foreach ( var lng in otherCommonLanguages )
{
var list = enLanguageKeys
. Except ( lng . Translations . Select ( t = > t . Key ) )
. ToList ( ) ;
if ( ! list . Any ( ) )
continue ;
message + = $"{++i}. '{lng.Language}' Keys: \r\n {string.Join(" \ r \ n ", list)} \r\n" ;
2021-06-01 14:00:55 +00:00
exists = true ;
// Save empty not found keys
//SaveNotFoundKeys(lng.Path, list);
2021-05-28 08:49:05 +00:00
}
2021-06-01 14:00:55 +00:00
Assert . AreEqual ( false , exists , message ) ;
2021-05-28 08:49:05 +00:00
}
2021-05-31 17:53:26 +00:00
2021-06-01 08:29:46 +00:00
public static void UpdateKeys ( string pathToJson , List < TranslationItem > newKeys )
{
if ( ! File . Exists ( pathToJson ) | | ! newKeys . Any ( ) )
return ;
var jsonTranslation = JObject . Parse ( File . ReadAllText ( pathToJson ) ) ;
var keys = newKeys . Select ( k = > k . Key ) . ToList ( ) ;
var properties = jsonTranslation . Properties ( ) . ToList ( ) ;
properties . ForEach ( p = >
{
var newKey = newKeys . Where ( k = > k . Key = = p . Name ) . FirstOrDefault ( ) ;
if ( newKey ! = null )
p . Value = newKey . Value ;
} ) ;
2021-06-01 10:49:37 +00:00
var result = new JObject ( properties ) ;
var sortedJsonString = JsonConvert . SerializeObject ( result , Formatting . Indented ) ;
File . WriteAllText ( pathToJson , sortedJsonString ) ;
}
2021-06-01 08:29:46 +00:00
2021-06-01 10:49:37 +00:00
public static void RemoveEmptyKeys ( string pathToJson , List < string > emptyKeys )
{
if ( ! File . Exists ( pathToJson ) | | ! emptyKeys . Any ( ) )
return ;
var jsonTranslation = JObject . Parse ( File . ReadAllText ( pathToJson ) ) ;
2021-06-01 08:29:46 +00:00
2021-06-01 10:49:37 +00:00
var properties = jsonTranslation . Properties ( ) . Where ( p = > ! emptyKeys . Contains ( p . Name ) ) . ToList ( ) ;
2021-06-01 08:29:46 +00:00
var result = new JObject ( properties ) ;
var sortedJsonString = JsonConvert . SerializeObject ( result , Formatting . Indented ) ;
File . WriteAllText ( pathToJson , sortedJsonString ) ;
}
public string GetWorkspace ( string path )
{
var folderName = Directory . GetParent ( Path . GetDirectoryName ( path ) ) . Name ;
switch ( folderName )
{
case "Client" :
return Workspaces . Find ( w = > w . Contains ( "ASC.Web.Client" ) ) ;
case "Files" :
return Workspaces . Find ( w = > w . Contains ( "ASC.Files" ) ) ;
case "Login" :
return Workspaces . Find ( w = > w . Contains ( "ASC.Web.Login" ) ) ;
case "People" :
return Workspaces . Find ( w = > w . Contains ( "ASC.People" ) ) ;
default :
return Path . Combine ( BasePath , "public\\locales" ) ;
}
}
2021-05-31 17:53:26 +00:00
[Test]
public void EmptyValueKeysTest ( )
{
2021-06-01 08:29:46 +00:00
// Uncomment if new keys are available
/ * var newTranslationsBasePath = @"D:\trans" ;
var translationFiles = from file in Directory . EnumerateFiles ( newTranslationsBasePath , "*.json" , SearchOption . AllDirectories )
select file ;
var newTranslationFiles = new List < KeyValuePair < string , TranslationFile > > ( ) ;
foreach ( var path in translationFiles )
{
var jsonTranslation = JObject . Parse ( File . ReadAllText ( path ) ) ;
var translationFile = new TranslationFile ( path , jsonTranslation . Properties ( )
. Select ( p = > new TranslationItem ( p . Name , ( string ) p . Value ) )
. ToList ( ) ) ;
var wsKey = GetWorkspace ( path ) ;
newTranslationFiles . Add ( new KeyValuePair < string , TranslationFile > ( wsKey , translationFile ) ) ;
} * /
2021-05-31 17:53:26 +00:00
var message = $"Next files have empty keys:\r\n\r\n" ;
var exists = false ;
var i = 0 ;
foreach ( var module in ModuleFolders )
{
if ( module . AvailableLanguages = = null )
continue ;
foreach ( var lng in module . AvailableLanguages )
{
2021-06-01 08:29:46 +00:00
var emptyTranslationItems = lng . Translations . Where ( f = > string . IsNullOrEmpty ( f . Value ) ) . ToList ( ) ;
2021-05-31 17:53:26 +00:00
2021-06-01 08:29:46 +00:00
if ( ! emptyTranslationItems . Any ( ) )
2021-05-31 17:53:26 +00:00
continue ;
exists = true ;
2021-06-01 08:29:46 +00:00
message + = $"{++i}. Language '{lng.Language}' (Count: {emptyTranslationItems.Count}). Path '{lng.Path}' " +
2021-05-31 17:53:26 +00:00
$"Empty keys:\r\n\r\n" ;
2021-06-01 08:29:46 +00:00
var emptyKeys = emptyTranslationItems . Select ( t = > t . Key ) . ToList ( ) ;
message + = string . Join ( "\r\n" , emptyKeys ) + "\r\n\r\n" ;
2021-06-01 10:49:37 +00:00
// Uncomment if you want to remove empty keys
//RemoveEmptyKeys(lng.Path, emptyKeys);
2021-06-01 08:29:46 +00:00
// Uncomment if new keys are available for saving
/ * var fileName = Path . GetFileName ( lng . Path ) ;
var newKeys = newTranslationFiles
. Where ( d = > lng . Path . Contains ( d . Key ) )
. Select ( d = > d . Value )
. Where ( t = > t . Language = = lng . Language
& & t . FileName = = fileName )
. SelectMany ( t = > t . Translations . Where ( t = > emptyKeys . Contains ( t . Key ) ) )
. ToList ( ) ;
UpdateKeys ( lng . Path , newKeys ) ; * /
2021-05-31 17:53:26 +00:00
}
}
2021-06-01 08:44:46 +00:00
foreach ( var lng in CommonTranslations )
{
var emptyTranslationItems = lng . Translations . Where ( f = > string . IsNullOrEmpty ( f . Value ) ) . ToList ( ) ;
if ( ! emptyTranslationItems . Any ( ) )
continue ;
exists = true ;
message + = $"{++i}. Language '{lng.Language}' (Count: {emptyTranslationItems.Count}). Path '{lng.Path}' " +
$"Empty keys:\r\n\r\n" ;
var emptyKeys = emptyTranslationItems . Select ( t = > t . Key ) . ToList ( ) ;
message + = string . Join ( "\r\n" , emptyKeys ) + "\r\n\r\n" ;
2021-06-01 10:49:37 +00:00
// Uncomment if you want to remove empty keys
//RemoveEmptyKeys(lng.Path, emptyKeys);
2021-06-01 08:44:46 +00:00
// Uncomment if new keys are available for saving
/ * var newKeys = newTranslationFiles
. Select ( d = > d . Value )
. Where ( t = > t . Language = = lng . Language )
. SelectMany ( t = > t . Translations . Where ( t = > emptyKeys . Contains ( t . Key ) ) )
. GroupBy ( t = > t . Key )
. Select ( g = > g . ToList ( ) . FirstOrDefault ( ) )
. ToList ( ) ;
UpdateKeys ( lng . Path , newKeys ) ; * /
}
2021-05-31 17:53:26 +00:00
Assert . AreEqual ( false , exists , message ) ;
}
2021-06-01 10:49:37 +00:00
[Test]
public void LanguageTranslatedPercentTest ( )
{
var message = $"Next languages translated less then 100%:\r\n\r\n" ;
var groupedByLng = TranslationFiles
. GroupBy ( t = > t . Language )
. Select ( g = > new
{
Language = g . Key ,
AllTranslated = g . ToList ( )
. SelectMany ( t = > t . Translations )
. ToList ( )
} )
. Select ( t = > new
{
t . Language ,
TotalKeysCount = t . AllTranslated . LongCount ( ) ,
EmptyKeysCount = t . AllTranslated
. Where ( t = > string . IsNullOrEmpty ( t . Value ) )
. LongCount ( )
} )
. ToList ( ) ;
var i = 0 ;
var exists = false ;
var expectedTotalKeysCount = groupedByLng . Where ( t = > t . Language = = "en" ) . Single ( ) . TotalKeysCount ;
foreach ( var lng in groupedByLng )
{
if ( lng . EmptyKeysCount = = 0 & & lng . TotalKeysCount = = expectedTotalKeysCount )
continue ;
exists = true ;
var translated = lng . TotalKeysCount = = expectedTotalKeysCount
2021-11-29 13:07:04 +00:00
? Math . Round ( 100f - ( lng . EmptyKeysCount * 100f / expectedTotalKeysCount ) , 1 )
: Math . Round ( lng . TotalKeysCount * 100f / expectedTotalKeysCount , 1 ) ;
2021-06-01 10:49:37 +00:00
message + = $"{++i}. Language '{lng.Language}' translated by '{translated}%'\r\n" ;
}
Assert . AreEqual ( false , exists , message ) ;
}
2021-06-01 14:00:55 +00:00
2021-06-01 17:00:36 +00:00
[Test]
public void NotTranslatedToastsTest ( )
{
var message = $"Next text not translated in toasts:\r\n\r\n" ;
var i = 0 ;
NotTranslatedToasts . GroupBy ( t = > t . Key )
. Select ( g = > new
{
FilePath = g . Key ,
Values = g . ToList ( )
} )
. ToList ( )
. ForEach ( t = >
{
message + = $"{++i}. Path='{t.FilePath}'\r\n\r\n{string.Join(" \ r \ n ", t.Values.Select(v => v.Value))}\r\n\r\n" ;
} ) ;
Assert . AreEqual ( 0 , NotTranslatedToasts . Count , message ) ;
}
2021-11-13 16:03:10 +00:00
[Test]
public void WrongTranslationVariablesTest ( )
{
var message = $"Next keys have wrong variables:\r\n\r\n" ;
var regVariables = new Regex ( "\\{\\{([^\\{].?[^\\}]+)\\}\\}" , RegexOptions . Compiled | RegexOptions . Multiline ) ;
var groupedByLng = TranslationFiles
. GroupBy ( t = > t . Language )
. Select ( g = > new
{
Language = g . Key ,
TranslationsWithVariables = g . ToList ( )
. SelectMany ( t = > t . Translations )
. Where ( k = > k . Value . IndexOf ( "{{" ) ! = - 1 )
. Select ( t = > new
{
t . Key ,
t . Value ,
Variables = regVariables . Matches ( t . Value )
. Select ( m = > m . Groups [ 1 ] ? . Value ? . Trim ( ) . Replace ( ", lowercase" , "" ) )
. ToList ( )
} )
. ToList ( )
} )
. ToList ( ) ;
var enWithVariables = groupedByLng
. Where ( t = > t . Language = = "en" )
. SelectMany ( t = > t . TranslationsWithVariables )
. ToList ( ) ;
var otherLanguagesWithVariables = groupedByLng
. Where ( t = > t . Language ! = "en" )
. ToList ( ) ;
var i = 0 ;
var errorsCount = 0 ;
foreach ( var lng in otherLanguagesWithVariables )
{
foreach ( var t in lng . TranslationsWithVariables )
{
var enKey = enWithVariables
. Where ( en = > en . Key = = t . Key )
. FirstOrDefault ( ) ;
if ( enKey = = null )
{
// wrong
message + = $"{++i}. lng='{lng.Language}' key='{t.Key}' has no 'en' language variant (!!!useless key!!!)\r\n\r\n" ;
errorsCount + + ;
continue ;
}
if ( enKey . Variables . Count ! = t . Variables . Count )
{
// wrong
message + = $"{++i}. lng='{lng.Language}' key='{t.Key}' has less variables then 'en' language have " +
$"(en={enKey.Variables.Count}|{lng.Language}={t.Variables.Count})\r\n" +
$"'en': '{enKey.Value}'\r\n'{lng.Language}': '{t.Value}'\r\n\r\n" ;
errorsCount + + ;
}
if ( ! t . Variables . All ( v = > enKey . Variables . Contains ( v ) ) )
{
// wrong
errorsCount + + ;
message + = $"{++i}. lng='{lng.Language}' key='{t.Key}' has not equals variables of 'en' language have\r\n\r\n" +
$"Have to be:\r\n'{enKey.Value}'\r\n\r\n{string.Join(" \ r \ n ", enKey.Variables)}\r\n\r\n" +
$"But in real:\r\n'{t.Value}'\r\n\r\n{string.Join(" \ r \ n ", t.Variables)} \r\n\r\n" ;
}
}
}
Assert . AreEqual ( 0 , errorsCount , message ) ;
}
2021-06-01 14:00:55 +00:00
/ * [ Test ]
public void TempTest ( )
{
var newTranslationsBasePath = @"D:\trans" ;
var translationFiles = from file in Directory . EnumerateFiles ( newTranslationsBasePath , "*.json" , SearchOption . AllDirectories )
select file ;
var newTranslationFiles = new List < TranslationFile > ( ) ;
foreach ( var path in translationFiles )
{
var jsonTranslation = JObject . Parse ( File . ReadAllText ( path ) ) ;
var translationFile = new TranslationFile ( path , jsonTranslation . Properties ( )
. Select ( p = > new TranslationItem ( p . Name , ( string ) p . Value ) )
. ToList ( ) ) ;
newTranslationFiles . Add ( translationFile ) ;
}
var groupedNewTranslation = newTranslationFiles
. GroupBy ( t = > t . Language )
. Select ( g = > new
{
Language = g . Key ,
Translations = g . ToList ( ) . SelectMany ( t = > t . Translations )
} )
. ToList ( ) ;
var enCommonTranslations = CommonTranslations . Where ( t = > t . Language = = "en" ) . ToList ( ) ;
foreach ( var lng in CommonTranslations . Where ( t = > t . Language ! = "en" ) )
{
var emptyTranslationItems = lng . Translations . Where ( f = > string . IsNullOrEmpty ( f . Value ) ) . ToList ( ) ;
if ( ! emptyTranslationItems . Any ( ) )
continue ;
var emptyKeys = emptyTranslationItems . Select ( t = > t . Key ) . ToList ( ) ;
var enCommonKeyValues = enCommonTranslations
. SelectMany ( t = > t . Translations )
. Where ( t = > emptyKeys . Contains ( t . Key ) )
. ToList ( ) ;
var newTranslationsKeysByOldEnContent = groupedNewTranslation
. Where ( t = > t . Language = = "en" )
. SelectMany ( t = > t . Translations )
. Where ( t = > enCommonKeyValues . Exists ( c = > c . Value = = t . Value ) )
//.Select(t => new TranslationItem(enCommonKeyValues.Find(c => c.Value == t.Value).Key, t.Value))
. ToList ( ) ;
// Uncomment if new keys are available for saving
var newKeys = new List < TranslationItem > ( ) ;
newTranslationFiles
. Where ( t = > t . Language = = lng . Language )
. SelectMany ( t = > t . Translations )
. ToList ( )
. ForEach ( t = >
{
var newItem = newTranslationsKeysByOldEnContent . Where ( k = > k . Key = = t . Key ) . FirstOrDefault ( ) ;
if ( newItem ! = null )
{
var value = t . Value ;
var newCommonKey = enCommonKeyValues . Find ( c = > c . Value = = newItem . Value ) . Key ;
if ( ! newKeys . Exists ( k = > k . Key = = newCommonKey ) )
{
newKeys . Add ( new TranslationItem ( newCommonKey , value ) ) ;
}
}
//if(newKeys.Exists(k => k.Key))
} ) ;
//.Where(t => newTranslationsKeysByOldEnContent.Exists(t.Key))
//.GroupBy(t => t.Key)
//.Select(g => g.ToList().FirstOrDefault())
//.ToList();
if ( newKeys . Any ( ) )
UpdateKeys ( lng . Path , newKeys ) ;
}
} * /
2021-05-20 15:11:43 +00:00
}
}