fix: google search
All checks were successful
Deploy QR Rapido / test (push) Successful in 4m22s
Deploy QR Rapido / build-and-push (push) Successful in 9m2s
Deploy QR Rapido / deploy-staging (push) Has been skipped
Deploy QR Rapido / deploy-production (push) Successful in 2m52s

This commit is contained in:
Ricardo Carneiro 2025-11-14 21:46:21 -03:00
parent 707dab8075
commit ea6eacc6c6
5 changed files with 138 additions and 137 deletions

View File

@ -216,92 +216,51 @@ namespace QRRapidoApp.Controllers
sitemapBuilder.AppendLine(@"<?xml version=""1.0"" encoding=""UTF-8""?>");
sitemapBuilder.AppendLine(@"<urlset xmlns=""http://www.sitemaps.org/schemas/sitemap/0.9"">");
// Static pages
void AppendUrl(string relativePath, string changeFreq, string priority, string? lastModOverride = null)
{
var normalizedPath = relativePath.StartsWith("/")
? relativePath
: $"/{relativePath}";
var lastModValue = lastModOverride ?? now;
sitemapBuilder.AppendLine($@"
<url>
<loc>{baseUrl}/</loc>
<lastmod>{now}</lastmod>
<changefreq>daily</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>{baseUrl}/pt/</loc>
<lastmod>{now}</lastmod>
<changefreq>daily</changefreq>
<priority>0.9</priority>
</url>
<url>
<loc>{baseUrl}/es/</loc>
<lastmod>{now}</lastmod>
<changefreq>daily</changefreq>
<priority>0.9</priority>
</url>
<url>
<loc>{baseUrl}/pt-BR/About</loc>
<lastmod>{now}</lastmod>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>{baseUrl}/es-PY/About</loc>
<lastmod>{now}</lastmod>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>{baseUrl}/pt-BR/Contact</loc>
<lastmod>{now}</lastmod>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>{baseUrl}/es-PY/Contact</loc>
<lastmod>{now}</lastmod>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>{baseUrl}/pt-BR/FAQ</loc>
<lastmod>{now}</lastmod>
<changefreq>weekly</changefreq>
<priority>0.9</priority>
</url>
<url>
<loc>{baseUrl}/es-PY/FAQ</loc>
<lastmod>{now}</lastmod>
<changefreq>weekly</changefreq>
<priority>0.9</priority>
</url>
<url>
<loc>{baseUrl}/pt-BR/HowToUse</loc>
<lastmod>{now}</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>{baseUrl}/es-PY/HowToUse</loc>
<lastmod>{now}</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>{baseUrl}/Pagamento/SelecaoPlano</loc>
<lastmod>{now}</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>{baseUrl}/privacy</loc>
<lastmod>{now}</lastmod>
<changefreq>monthly</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>{baseUrl}/terms</loc>
<lastmod>{now}</lastmod>
<changefreq>monthly</changefreq>
<priority>0.5</priority>
<loc>{baseUrl}{normalizedPath}</loc>
<lastmod>{lastModValue}</lastmod>
<changefreq>{changeFreq}</changefreq>
<priority>{priority}</priority>
</url>");
}
// 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
@ -310,16 +269,14 @@ namespace QRRapidoApp.Controllers
foreach (var article in allArticles)
{
var slug = article.Title.ToLower().Replace(" ", "-");
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");
sitemapBuilder.AppendLine($@"
<url>
<loc>{baseUrl}/{article.Culture}/tutoriais/{slug}</loc>
<lastmod>{lastMod}</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>");
AppendUrl($"/{article.Culture}/tutoriais/{encodedSlug}", "weekly", "0.8", lastMod);
}
_logger.LogInformation("Generated sitemap with {Count} tutorial articles", allArticles.Count);

View File

@ -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<LanguageRedirectionMiddleware> _logger;
private readonly string[] _supportedCultures = { "pt-BR", "es-PY" };
private readonly Dictionary<string, string> _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<LanguageRedirectionMiddleware> 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[]

View File

@ -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 @@
}
}
<!DOCTYPE html>
<html lang="pt-BR">
<html lang="@currentCulture">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
@ -47,9 +48,8 @@
<link rel="canonical" href="@Context.Request.GetDisplayUrl()">
<!-- Hreflang for multilingual -->
<link rel="alternate" hreflang="pt-BR" href="https://qrrapido.site/pt/">
<link rel="alternate" hreflang="es" href="https://qrrapido.site/es/">
<link rel="alternate" hreflang="en" href="https://qrrapido.site/en/">
<link rel="alternate" hreflang="pt-BR" href="https://qrrapido.site/pt-BR/">
<link rel="alternate" hreflang="es-PY" href="https://qrrapido.site/es-PY/">
<link rel="alternate" hreflang="x-default" href="https://qrrapido.site/">
<!-- Open Graph -->

View File

@ -176,7 +176,7 @@
<div class="list-group list-group-flush">
@foreach (var related in Model.RelatedArticles)
{
<a href="/@ViewBag.Culture/tutoriais/@related.Title.ToLower().Replace(" ", "-")"
<a href="/@ViewBag.Culture/tutoriais/@related.Slug"
class="list-group-item list-group-item-action">
<h6 class="mb-1">@related.Title</h6>
<p class="mb-1 text-muted small">@related.Description</p>

View File

@ -2,8 +2,6 @@ User-agent: *
Allow: /
Sitemap: https://qrrapido.site/sitemap.xml
Sitemap: https://qrrapido.site/pt-BR/sitemap.xml
Sitemap: https://qrrapido.site/es-PY/sitemap.xml
Disallow: /Admin/
Disallow: /Identity/