diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/es.json b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/es.json
new file mode 100644
index 0000000000..25ed44d7ad
--- /dev/null
+++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpValidation/es.json
@@ -0,0 +1,34 @@
+{
+ "culture": "es",
+ "texts": {
+ "'{0}' and '{1}' do not match.": "'{0} \" y \"{1} \" no coinciden.",
+ "The {0} field is not a valid credit card number.": "{0} no es un número de tarjeta de crédito.",
+ "{0} is not valid.": "{0} no es válido.",
+ "The {0} field is not a valid e-mail address.": "{0} no es una dirección de correo electrónico válida.",
+ "The {0} field only accepts files with the following extensions: {1}": "{0} campo sólo acepta archivos con las siguientes extensiones: {1}",
+ "The field {0} must be a string or array type with a maximum length of '{1}'.": "El campo {0} debe ser una cadena o un array con una longitud máxima de '{1}'.",
+ "The field {0} must be a string or array type with a minimum length of '{1}'.": "El campo {0} debe ser una cadena o un array con una longitud mínima de '{1}'.",
+ "The {0} field is not a valid phone number.": "{0} no es un número de teléfono válido.",
+ "The field {0} must be between {1} and {2}.": "El campo {0} debe ser entre {1} y {2}.",
+ "The field {0} must match the regular expression '{1}'.": "El campo {0} debe coincidir con la expresión regular '{1}'.",
+ "The {0} field is required.": "La {0} campo es obligatorio.",
+ "The field {0} must be a string with a maximum length of {1}.": "El campo {0} debe ser una cadena con una longitud máxima de {1}.",
+ "The field {0} must be a string with a minimum length of {2} and a maximum length of {1}.": "El campo {0} debe ser una cadena con una longitud mínima de {2} y una longitud máxima de {1}.",
+ "The {0} field is not a valid fully-qualified http, https, or ftp URL.": "El campo {0} no es una dirección URL válida http, https o ftp.",
+ "The field {0} is invalid.": "El campo {0} no es válido.",
+ "ThisFieldIsNotAValidCreditCardNumber.": "Este campo no es un número de tarjeta de crédito.",
+ "ThisFieldIsNotValid.": "Este campo no es válido.",
+ "ThisFieldIsNotAValidEmailAddress.": "Este campo no es una dirección de correo electrónico válida.",
+ "ThisFieldOnlyAcceptsFilesWithTheFollowingExtensions:{0}": "Este campo sólo acepta archivos con las siguientes extensiones: {0}",
+ "ThisFieldMustBeAStringOrArrayTypeWithAMaximumLengthoOf{0}": "Este campo debe ser una cadena o un array con una longitud máxima de '{0}'.",
+ "ThisFieldMustBeAStringOrArrayTypeWithAMinimumLengthOf{0}": "Este campo debe ser una cadena o un array con una longitud mínima de '{0}'.",
+ "ThisFieldIsNotAValidPhoneNumber.": "Este campo no es un número de teléfono válido.",
+ "ThisFieldMustBeBetween{0}And{1}": "Este campo debe tener un valor entre {0} y {1}.",
+ "ThisFieldMustMatchTheRegularExpression{0}": "Este campo debe coincidir con la expresión regular '{0}'.",
+ "ThisFieldIsRequired.": "Este campo es obligatorio.",
+ "ThisFieldMustBeAStringWithAMaximumLengthOf{0}": "Este campo debe ser una cadena de caracteres con una longitud máxima de {0}.",
+ "ThisFieldMustBeAStringWithAMinimumLengthOf{1}AndAMaximumLengthOf{0}": "Este campo debe ser una cadena de caracteres con una longitud mínima de {1} y una longitud máxima de {0}.",
+ "ThisFieldIsNotAValidFullyQualifiedHttpHttpsOrFtpUrl": "Este campo no es una dirección URL válida http, https o ftp.",
+ "ThisFieldIsInvalid.": "Este campo no es válido."
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/es.json b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/es.json
new file mode 100644
index 0000000000..ba27a9193c
--- /dev/null
+++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/es.json
@@ -0,0 +1,6 @@
+{
+ "culture": "es",
+ "texts": {
+ "Menu:Administration": "Administración"
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json
new file mode 100644
index 0000000000..4997156c8d
--- /dev/null
+++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json
@@ -0,0 +1,58 @@
+{
+ "culture": "es",
+ "texts": {
+ "InternalServerErrorMessage": "Ocurrió un error interno en su pedido!",
+ "ValidationErrorMessage": "Su pedido no es válido!",
+ "ValidationNarrativeErrorMessageTitle": "Los siguientes errores se encontraton durante la validación.",
+ "DefaultErrorMessage": "Ocurrió un error!",
+ "DefaultErrorMessageDetail": "El servidor no envió el detalle del error.",
+ "DefaultErrorMessage401": "Usted no ha iniciado sessión!",
+ "DefaultErrorMessage401Detail": "Debe iniciar sessión para ejecutar esta operación.",
+ "DefaultErrorMessage403": "Usted no está autorizado!",
+ "DefaultErrorMessage403Detail": "Usted no puede hacer esta operación!",
+ "DefaultErrorMessage404": "No se encontró el recurso!",
+ "DefaultErrorMessage404Detail": "El recurso solicitado no se encontró en el servidor!",
+ "EntityNotFoundErrorMessage": "No hay una entidad {0} con el id = {1}!",
+ "Error": "Error",
+ "AreYouSure": "¿Está seguro?",
+ "Cancel": "Cancelar",
+ "Yes": "Si",
+ "No": "No",
+ "Close": "Cerrar",
+ "Save": "Guardar",
+ "SavingWithThreeDot": "Guardando...",
+ "Actions": "Acciones",
+ "Delete": "Eliminar",
+ "Edit": "Editar",
+ "Refresh": "Refrescar",
+ "ProcessingWithThreeDot": "Procesando...",
+ "LoadingWithThreeDot": "Cargando...",
+ "Welcome": "Bienvenido",
+ "Login": "Iniciar session",
+ "Register": "Registrarse",
+ "Logout": "Cerrar sessión",
+ "Submit": "Enviar",
+ "Back": "Atrás",
+ "PagerSearch": "Buscar",
+ "PagerNext": "Siguiente",
+ "PagerPrevious": "Anterior",
+ "PagerFirst": "Primero",
+ "PagerLast": "Último",
+ "PagerInfo": "Mostrando desde _START_ hasta _END_ total _TOTAL_",
+ "PagerInfoEmpty": "Mostrando desde 0 hasta 0 de 0 registros",
+ "PagerInfoFiltered": "(filtrado de un total de _MAX_ registros)",
+ "NoDataAvailableInDatatable": "No hay datos",
+ "PagerShowMenuEntries": "Mostrar _MENU_ registros",
+ "DatatableActionDropdownDefaultText": "Acciones",
+ "ChangePassword": "Cambiar contraseña",
+ "PersonalInfo": "My perfil",
+ "AreYouSureYouWantToCancelEditingWarningMessage": "Tiene cambios sin guardar.",
+ "UnhandledException": "Excepción no controlada!",
+ "401Message": "No autorizado",
+ "403Message": "Prohibido",
+ "404Message": "La página no existe",
+ "500Message": "Error interno del servidor",
+ "GoHomePage": "Ir a la página principal",
+ "GoBack": "Atras"
+ }
+}
diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/AbpLocalization_Tests.cs b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/AbpLocalization_Tests.cs
index eab7a580c5..24433824a3 100644
--- a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/AbpLocalization_Tests.cs
+++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/AbpLocalization_Tests.cs
@@ -66,6 +66,12 @@ namespace Volo.Abp.Localization
{
_localizer["Car"].Value.ShouldBe("Auto");
}
+
+ using (AbpCultureHelper.Use("es"))
+ {
+ _localizer["Car"].Value.ShouldBe("Auto");
+ }
+
}
[Fact]
@@ -85,6 +91,12 @@ namespace Volo.Abp.Localization
{
_localizer["SeeYou"].Value.ShouldBe("Ci vediamo");
}
+
+ using (AbpCultureHelper.Use("es"))
+ {
+ _localizer["SeeYou"].Value.ShouldBe("Nos vemos");
+ }
+
}
[Fact]
@@ -102,6 +114,15 @@ namespace Volo.Abp.Localization
{
_localizer["USA"].Value.ShouldBe("Amerika Birleşik Devletleri"); //Inherited from CountryNames/tr.json
}
+
+ using (AbpCultureHelper.Use("es"))
+ {
+ _localizer["USA"].Value.ShouldBe("Estados unidos de America"); //Inherited from CountryNames/es.json
+ _localizer["ThisFieldIsRequired"].Value.ShouldBe("El campo no puede estar vacío"); //Inherited from Validation/es.json
+
+ _localizer.GetAllStrings().ShouldContain(ls => ls.Name == "USA");
+ }
+
}
[Fact]
@@ -111,6 +132,13 @@ namespace Volo.Abp.Localization
{
_localizer["MaxLenghtErrorMessage", 42].Value.ShouldBe("This field's length can be maximum of '42' chars"); //Overriden in Source/en.json
}
+
+ using (AbpCultureHelper.Use("es"))
+ {
+ _localizer["MaxLenghtErrorMessage", 42].Value.ShouldBe("El campo puede tener un máximo de '42' caracteres"); //Overriden in Source/es.json
+ }
+
+
}
[Fact]
@@ -121,6 +149,10 @@ namespace Volo.Abp.Localization
_localizer.WithCulture(CultureInfo.GetCultureInfo("tr"))["Car"].Value.ShouldBe("Araba");
_localizer.WithCulture(CultureInfo.GetCultureInfo("tr"))["CarPlural"].Value.ShouldBe("Araba");
+
+ _localizer.WithCulture(CultureInfo.GetCultureInfo("es"))["Car"].Value.ShouldBe("Auto");
+ _localizer.WithCulture(CultureInfo.GetCultureInfo("es"))["CarPlural"].Value.ShouldBe("Autos");
+
}
[Fact]
@@ -142,6 +174,24 @@ namespace Volo.Abp.Localization
ls.ResourceNotFound == false
);
}
+
+ using (AbpCultureHelper.Use("es"))
+ {
+ var localizedStrings = _localizer.GetAllStrings(true).ToList();
+
+ localizedStrings.ShouldContain(
+ ls => ls.Name == "FortyTwo" &&
+ ls.Value == "Cuarenta y dos" &&
+ ls.ResourceNotFound == false
+ );
+
+ localizedStrings.ShouldContain(
+ ls => ls.Name == "Universe" &&
+ ls.Value == "Universo" &&
+ ls.ResourceNotFound == false
+ );
+ }
+
}
[Fact]
@@ -161,6 +211,22 @@ namespace Volo.Abp.Localization
ls.ResourceNotFound == false
);
}
+
+ using (AbpCultureHelper.Use("es"))
+ {
+ var localizedStrings = _localizer.GetAllStrings(false).ToList();
+
+ localizedStrings.ShouldNotContain(
+ ls => ls.Name == "FortyTwo"
+ );
+
+ localizedStrings.ShouldContain(
+ ls => ls.Name == "Universe" &&
+ ls.Value == "Universo" &&
+ ls.ResourceNotFound == false
+ );
+ }
+
}
[Fact]
diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/es.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/es.json
new file mode 100644
index 0000000000..d9b29895b8
--- /dev/null
+++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/es.json
@@ -0,0 +1,7 @@
+{
+ "culture": "es",
+ "texts": {
+ "USA": "Estados unidos de América",
+ "Brazil": "Brasil"
+ }
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/es.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/es.json
new file mode 100644
index 0000000000..04e85b5f12
--- /dev/null
+++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/es.json
@@ -0,0 +1,7 @@
+{
+ "culture": "es",
+ "texts": {
+ "ThisFieldIsRequired": "El campo no puede estar vacío",
+ "MaxLenghtErrorMessage": "El campo puede tener un máximo de '{0}' caracteres"
+ }
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/es.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/es.json
new file mode 100644
index 0000000000..7b68ff6f2c
--- /dev/null
+++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/es.json
@@ -0,0 +1,11 @@
+{
+ "culture": "es",
+ "texts": {
+ "Hello {0}.": "Hola {0}.",
+ "Car": "Auto",
+ "CarPlural": "Autos",
+ "MaxLenghtErrorMessage": "El campo puede tener un máximo de '{0}' caracteres",
+ "Universe": "Universo",
+ "FortyTwo": "Curenta y dos"
+ }
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/es.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/es.json
new file mode 100644
index 0000000000..f02a049420
--- /dev/null
+++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/es.json
@@ -0,0 +1,6 @@
+{
+ "culture": "es",
+ "texts": {
+ "SeeYou": "Nos vemos"
+ }
+}
\ No newline at end of file