From ea6eacc6c69e8c213984e6a44648ce3d6216008c Mon Sep 17 00:00:00 2001 From: Ricardo Carneiro Date: Fri, 14 Nov 2025 21:46:21 -0300 Subject: [PATCH] fix: google search --- Controllers/HomeController.cs | 215 ++++++++------------ Middleware/LanguageRedirectionMiddleware.cs | 48 ++++- Views/Shared/_Layout.cshtml | 8 +- Views/Tutoriais/Article.cshtml | 2 +- wwwroot/robots.txt | 2 - 5 files changed, 138 insertions(+), 137 deletions(-) diff --git a/Controllers/HomeController.cs b/Controllers/HomeController.cs index 191d11f..652c97b 100644 --- a/Controllers/HomeController.cs +++ b/Controllers/HomeController.cs @@ -205,134 +205,91 @@ namespace QRRapidoApp.Controllers return Ok(new { status = "healthy", timestamp = DateTime.UtcNow }); } - // Sitemap endpoint for SEO - [Route("sitemap.xml")] - public async Task Sitemap() - { - var baseUrl = "https://qrrapido.site"; - var now = DateTime.UtcNow.ToString("yyyy-MM-dd"); - - var sitemapBuilder = new System.Text.StringBuilder(); - sitemapBuilder.AppendLine(@""); - sitemapBuilder.AppendLine(@""); - - // Static pages - sitemapBuilder.AppendLine($@" - - {baseUrl}/ - {now} - daily - 1.0 - - - {baseUrl}/pt/ - {now} - daily - 0.9 - - - {baseUrl}/es/ - {now} - daily - 0.9 - - - {baseUrl}/pt-BR/About - {now} - monthly - 0.8 - - - {baseUrl}/es-PY/About - {now} - monthly - 0.8 - - - {baseUrl}/pt-BR/Contact - {now} - monthly - 0.8 - - - {baseUrl}/es-PY/Contact - {now} - monthly - 0.8 - - - {baseUrl}/pt-BR/FAQ - {now} - weekly - 0.9 - - - {baseUrl}/es-PY/FAQ - {now} - weekly - 0.9 - - - {baseUrl}/pt-BR/HowToUse - {now} - weekly - 0.8 - - - {baseUrl}/es-PY/HowToUse - {now} - weekly - 0.8 - - - {baseUrl}/Pagamento/SelecaoPlano - {now} - weekly - 0.8 - - - {baseUrl}/privacy - {now} - monthly - 0.5 - - - {baseUrl}/terms - {now} - monthly - 0.5 - "); - - // Dynamic tutorial pages - try - { - var allArticles = await _markdownService.GetAllArticlesForSitemapAsync(); - - foreach (var article in allArticles) - { - var slug = article.Title.ToLower().Replace(" ", "-"); - var lastMod = article.LastMod.ToString("yyyy-MM-dd"); - - sitemapBuilder.AppendLine($@" - - {baseUrl}/{article.Culture}/tutoriais/{slug} - {lastMod} - weekly - 0.8 - "); - } - - _logger.LogInformation("Generated sitemap with {Count} tutorial articles", allArticles.Count); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error adding tutorials to sitemap"); - } - - sitemapBuilder.AppendLine(""); - - return Content(sitemapBuilder.ToString(), "application/xml"); - } + // Sitemap endpoint for SEO + [Route("sitemap.xml")] + public async Task Sitemap() + { + var baseUrl = "https://qrrapido.site"; + var now = DateTime.UtcNow.ToString("yyyy-MM-dd"); + + var sitemapBuilder = new System.Text.StringBuilder(); + sitemapBuilder.AppendLine(@""); + sitemapBuilder.AppendLine(@""); + + void AppendUrl(string relativePath, string changeFreq, string priority, string? lastModOverride = null) + { + var normalizedPath = relativePath.StartsWith("/") + ? relativePath + : $"/{relativePath}"; + + var lastModValue = lastModOverride ?? now; + + sitemapBuilder.AppendLine($@" + + {baseUrl}{normalizedPath} + {lastModValue} + {changeFreq} + {priority} + "); + } + + // Core entry points + AppendUrl("/", "daily", "1.0"); + AppendUrl("/pt-BR", "daily", "0.9"); + AppendUrl("/es-PY", "daily", "0.9"); + + var cultures = new[] { "pt-BR", "es-PY" }; + var informationalPages = new[] + { + new { Path = "Home/About", ChangeFreq = "monthly", Priority = "0.8" }, + new { Path = "Home/Contact", ChangeFreq = "monthly", Priority = "0.8" }, + new { Path = "Home/FAQ", ChangeFreq = "weekly", Priority = "0.9" }, + new { Path = "Home/HowToUse", ChangeFreq = "weekly", Priority = "0.8" }, + new { Path = "Home/Privacy", ChangeFreq = "monthly", Priority = "0.5" }, + new { Path = "Home/Terms", ChangeFreq = "monthly", Priority = "0.5" } + }; + + foreach (var page in informationalPages) + { + AppendUrl($"/{page.Path}", page.ChangeFreq, page.Priority); + } + + foreach (var culture in cultures) + { + foreach (var page in informationalPages) + { + AppendUrl($"/{culture}/{page.Path}", page.ChangeFreq, page.Priority); + } + } + + // Dynamic tutorial pages + try + { + var allArticles = await _markdownService.GetAllArticlesForSitemapAsync(); + + foreach (var article in allArticles) + { + var slug = !string.IsNullOrWhiteSpace(article.Slug) + ? article.Slug + : article.Title.ToLower().Replace(" ", "-"); + + var encodedSlug = System.Uri.EscapeDataString(slug); + var lastMod = article.LastMod.ToString("yyyy-MM-dd"); + + AppendUrl($"/{article.Culture}/tutoriais/{encodedSlug}", "weekly", "0.8", lastMod); + } + + _logger.LogInformation("Generated sitemap with {Count} tutorial articles", allArticles.Count); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error adding tutorials to sitemap"); + } + + sitemapBuilder.AppendLine(""); + + return Content(sitemapBuilder.ToString(), "application/xml"); + } } //public class ErrorViewModel @@ -340,4 +297,4 @@ namespace QRRapidoApp.Controllers // public string? RequestId { get; set; } // public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); //} -} \ No newline at end of file +} diff --git a/Middleware/LanguageRedirectionMiddleware.cs b/Middleware/LanguageRedirectionMiddleware.cs index 9f99784..d6851eb 100644 --- a/Middleware/LanguageRedirectionMiddleware.cs +++ b/Middleware/LanguageRedirectionMiddleware.cs @@ -1,4 +1,5 @@ using System.Globalization; +using System.Linq; namespace QRRapidoApp.Middleware { @@ -7,6 +8,12 @@ namespace QRRapidoApp.Middleware private readonly RequestDelegate _next; private readonly ILogger _logger; private readonly string[] _supportedCultures = { "pt-BR", "es-PY" }; + private readonly Dictionary _cultureAliases = new(StringComparer.OrdinalIgnoreCase) + { + { "pt", "pt-BR" }, + { "pt-br", "pt-BR" }, + { "es", "es-PY" } + }; private const string DefaultCulture = "pt-BR"; public LanguageRedirectionMiddleware(RequestDelegate next, ILogger logger) @@ -19,6 +26,11 @@ namespace QRRapidoApp.Middleware { var path = context.Request.Path.Value?.TrimStart('/') ?? ""; + if (TryHandleCultureAlias(context, path)) + { + return; + } + if (HasCultureInPath(path) || IsSpecialRoute(path)) { await _next(context); @@ -63,6 +75,40 @@ namespace QRRapidoApp.Middleware return _supportedCultures.Contains(segments[0]); } + private bool TryHandleCultureAlias(HttpContext context, string path) + { + if (string.IsNullOrEmpty(path)) + { + return false; + } + + var segments = path.Split('/', StringSplitOptions.RemoveEmptyEntries); + if (segments.Length == 0) + { + return false; + } + + var firstSegment = segments[0]; + if (_cultureAliases.TryGetValue(firstSegment, out var mappedCulture)) + { + var remainingSegments = segments.Length > 1 + ? "/" + string.Join('/', segments.Skip(1)) + : string.Empty; + + var redirectUrl = $"/{mappedCulture}{remainingSegments}"; + if (context.Request.QueryString.HasValue) + { + redirectUrl += context.Request.QueryString.Value; + } + + _logger.LogInformation("Redirecting alias '{Alias}' to canonical culture URL: {RedirectUrl}", firstSegment, redirectUrl); + context.Response.Redirect(redirectUrl, permanent: true); + return true; + } + + return false; + } + private bool IsSpecialRoute(string path) { var specialRoutes = new[] @@ -110,4 +156,4 @@ namespace QRRapidoApp.Middleware return DefaultCulture; } } -} \ No newline at end of file +} diff --git a/Views/Shared/_Layout.cshtml b/Views/Shared/_Layout.cshtml index 4beaf36..fc0df62 100644 --- a/Views/Shared/_Layout.cshtml +++ b/Views/Shared/_Layout.cshtml @@ -8,6 +8,7 @@ @{ var isDevelopment = HostEnvironment?.IsDevelopment() ?? false; var isPremiumUser = false; + var currentCulture = System.Globalization.CultureInfo.CurrentUICulture?.Name ?? "pt-BR"; if (User?.Identity?.IsAuthenticated == true) { @@ -26,7 +27,7 @@ } } - + @@ -47,9 +48,8 @@ - - - + + diff --git a/Views/Tutoriais/Article.cshtml b/Views/Tutoriais/Article.cshtml index c7ca847..99dbafb 100644 --- a/Views/Tutoriais/Article.cshtml +++ b/Views/Tutoriais/Article.cshtml @@ -176,7 +176,7 @@