diff --git a/common/src/DbLocalizationProvider/LocalizationProvider.cs b/common/src/DbLocalizationProvider/LocalizationProvider.cs
index ecfcb57a..ca5a86b5 100644
--- a/common/src/DbLocalizationProvider/LocalizationProvider.cs
+++ b/common/src/DbLocalizationProvider/LocalizationProvider.cs
@@ -9,12 +9,9 @@
 using System.Text.RegularExpressions;
 using DbLocalizationProvider.Abstractions;
 using DbLocalizationProvider.Internal;
-using DbLocalizationProvider.Json;
 using DbLocalizationProvider.Queries;
 using DbLocalizationProvider.Sync;
 using Microsoft.Extensions.Options;
-using Newtonsoft.Json;
-using JsonConverter = DbLocalizationProvider.Json.JsonConverter;
 
 namespace DbLocalizationProvider;
 
@@ -28,8 +25,7 @@ public class LocalizationProvider : ILocalizationProvider
     private readonly ResourceKeyBuilder _keyBuilder;
     internal readonly IQueryExecutor _queryExecutor;
     private readonly ScanState _scanState;
-    private readonly JsonConverter _converter;
-    private readonly JsonSerializer _serializer;
+    private readonly ReflectionConverter _reflectionConverter;
 
     /// <summary>
     /// Creates new localization provider with all the required settings and services injected.
@@ -54,12 +50,8 @@ public LocalizationProvider(
         _fallbackCollection = context.Value._fallbackCollection;
         _queryExecutor = queryExecutor;
         _scanState = scanState;
-        
-        _converter = new JsonConverter(_queryExecutor, _scanState);
-        _serializer = new JsonSerializer
-        {
-            ContractResolver = new StaticPropertyContractResolver()
-        };
+
+        _reflectionConverter = new ReflectionConverter(_queryExecutor, _scanState);
     }
 
     /// <summary>
@@ -228,20 +220,7 @@ public T Translate<T>()
     /// <returns>Translated class</returns>
     public T Translate<T>(CultureInfo language)
     {
-        var className = typeof(T).FullName;
-
-        var json = _converter.GetJson(className, language.Name, _fallbackCollection);
-
-        // get the actual class Json representation (we need to select token through FQN of the class)
-        // to supported nested classes - we need to fix a bit resource key name
-        var jsonToken = json.SelectToken(className.Replace('+', '.'));
-
-        if (jsonToken == null)
-        {
-            return (T)Activator.CreateInstance(typeof(T), new object[] { });
-        }
-
-        return jsonToken.ToObject<T>(_serializer);
+        return _reflectionConverter.Convert<T>(language.Name, _fallbackCollection);
     }
 
     /// <summary>
diff --git a/common/src/DbLocalizationProvider/ReflectionConverter.cs b/common/src/DbLocalizationProvider/ReflectionConverter.cs
new file mode 100644
index 00000000..ab47a9f5
--- /dev/null
+++ b/common/src/DbLocalizationProvider/ReflectionConverter.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using DbLocalizationProvider.Abstractions;
+using DbLocalizationProvider.Queries;
+using DbLocalizationProvider.Sync;
+
+namespace DbLocalizationProvider;
+
+public class ReflectionConverter
+{
+    private readonly IQueryExecutor _queryExecutor;
+    private readonly ScanState _scanState;
+
+    public ReflectionConverter(IQueryExecutor queryExecutor, ScanState scanState)
+    {
+        _queryExecutor = queryExecutor;
+        _scanState = scanState;
+    }
+
+    public T Convert<T>(string languageName, FallbackLanguagesCollection fallbackCollection)
+    {
+        // TODO: Can the dictionary be cached?
+        // TODO: Can we go around query execution and use repository directly?
+        var resources = _queryExecutor
+            .Execute(new GetAllResources.Query())
+            .ToDictionary(x => x.ResourceKey, StringComparer.Ordinal);
+
+        var newObject = Activator.CreateInstance<T>();
+
+        FillProperties(newObject!, languageName, resources, fallbackCollection);
+        
+        return newObject;
+    }
+
+    private void FillProperties(object instance, string languageName, Dictionary<string, LocalizationResource> resources, FallbackLanguagesCollection fallbackCollection)
+    {
+        var type = instance!.GetType();
+        var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static);
+        foreach (var propertyInfo in properties)
+        {
+            if (propertyInfo.MemberType == MemberTypes.NestedType)
+            {
+                var nestedObject = Activator.CreateInstance(propertyInfo.PropertyType);
+                if (nestedObject == null)
+                {
+                    continue;
+                }
+                
+                FillProperties(nestedObject, languageName, resources, fallbackCollection);
+                
+                propertyInfo.SetValue(instance, nestedObject);
+            }
+            
+            if (propertyInfo.PropertyType != typeof(string))
+            {
+                continue;
+            }
+            
+            string? translation;
+            string key = $"{type.FullName}.{propertyInfo.Name}";
+            if (_scanState.UseResourceAttributeCache.TryGetValue(key, out var targetResourceKey))
+            {
+                if (resources.TryGetValue(targetResourceKey, out var foundResource))
+                {
+                    translation = foundResource.Translations.GetValueWithFallback(
+                        languageName,
+                        fallbackCollection.GetFallbackLanguages(languageName));
+                    
+                    propertyInfo.SetValue(instance, translation);
+                    continue;
+                }
+            }
+            
+            if (!resources.TryGetValue(key, out var resource))
+            {
+                continue;
+            }
+            
+            translation = resource.Translations.GetValueWithFallback(
+                languageName,
+                fallbackCollection.GetFallbackLanguages(languageName));
+        
+            propertyInfo.SetValue(instance, translation);
+        }
+    }
+}