-
Notifications
You must be signed in to change notification settings - Fork 8
feat(blog): handle link hreflang tags #454
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughThis change introduces automated management of hreflang SEO metadata across the blog platform. New utilities and store methods facilitate mapping between article locales and languages, and route configurations now support automatic hreflang generation. The Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Router
participant ArticleDetailsStore
participant SeoStore
participant SeoService
participant DOM
User->>Router: Navigates to article route
Router->>ArticleDetailsStore: Fetch article details
ArticleDetailsStore->>ArticleDetailsStore: buildArticleHreflangEntries()
ArticleDetailsStore->>SeoStore: setHreflang(entries)
SeoStore->>SeoService: setHreflang(entries)
SeoService->>DOM: Update hreflang <link> tags
Possibly related PRs
Poem
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
PR is detected, will deploy to dev environment |
Deployed to dev environment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
libs/blog/shared/util-seo/src/lib/services/seo.service.ts (1)
70-72
: Use optional chaining for cleaner codeThe nested property access can be simplified using optional chaining as suggested by the static analyzer.
- if (routeData && routeData['seo'] && routeData['seo']['autoHrefLang']) { + if (routeData?.['seo']?.['autoHrefLang']) { this.handleAutoHreflang(seoConfig.baseUrl, this._router.url); }🧰 Tools
🪛 Biome (1.9.4)
[error] 70-70: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
libs/blog-contracts/articles/src/lib/articles.ts
(1 hunks)libs/blog/articles/data-access/src/lib/state/article-details.store.ts
(3 hunks)libs/blog/articles/feature-shell/src/lib/routes.ts
(4 hunks)libs/blog/shared/util-seo/src/lib/services/seo.service.ts
(6 hunks)libs/blog/shared/util-seo/src/lib/state/seo.store-feature.ts
(2 hunks)libs/blog/shell/feature-shell-web/src/lib/blog-shell.routes.ts
(3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
libs/blog/shared/util-seo/src/lib/state/seo.store-feature.ts (1)
libs/blog/shared/util-seo/src/lib/services/seo.service.ts (1)
HreflangEntry
(16-19)
libs/blog/articles/data-access/src/lib/state/article-details.store.ts (2)
libs/blog-contracts/articles/src/lib/articles.ts (2)
Article
(106-132)articleLocaleToLangMap
(154-157)libs/blog/shared/util-seo/src/lib/services/seo.service.ts (1)
HreflangEntry
(16-19)
libs/blog-contracts/articles/src/lib/articles.ts (1)
libs/blog-contracts/articles/src/lib/languages.ts (1)
Lang
(10-10)
🪛 Biome (1.9.4)
libs/blog/shared/util-seo/src/lib/services/seo.service.ts
[error] 70-70: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🔇 Additional comments (14)
libs/blog-contracts/articles/src/lib/articles.ts (1)
154-157
: LGTM! Well-implemented reverse mapping for hreflang support.The
articleLocaleToLangMap
correctly provides the inverse mapping ofarticleLangToLocaleMap
, enabling conversion fromArticleLocale
toLang
codes. The type safety withsatisfies Record<ArticleLocale, Lang>
ensures consistency with the type system.libs/blog/articles/feature-shell/src/lib/routes.ts (1)
16-16
: LGTM! Consistent implementation of autoHrefLang flag.The addition of
autoHrefLang: true
to the SEO data is consistent across all article category routes. This enables automatic hreflang tag generation for improved multilingual SEO support.Also applies to: 28-28, 40-40, 52-52
libs/blog/shell/feature-shell-web/src/lib/blog-shell.routes.ts (1)
34-34
: LGTM! Comprehensive autoHrefLang implementation across blog shell routes.The consistent addition of
autoHrefLang: true
to SEO data objects across all major content routes enables automatic hreflang tag generation. The creation of new SEO data objects for routes that previously lacked them (author detail and writing rules) follows the correct pattern.Also applies to: 51-51, 59-61, 69-69, 83-85
libs/blog/shared/util-seo/src/lib/state/seo.store-feature.ts (2)
6-6
: LGTM! Correct import addition for HreflangEntry type.The import statement properly includes the
HreflangEntry
type needed for the new hreflang methods.
17-22
: LGTM! Well-implemented hreflang methods following established patterns.The
setHreflang
andclearHreflang
methods correctly delegate to theSeoService
and follow the same pattern as other methods in the store feature. The type safety is maintained with proper use of theHreflangEntry[]
parameter type.libs/blog/articles/data-access/src/lib/state/article-details.store.ts (3)
14-18
: LGTM!The imports are properly organized and the necessary dependencies for hreflang functionality are correctly imported.
78-87
: LGTM!The hreflang handling logic is correctly implemented. It properly sets hreflang entries when available and clears them when not, ensuring clean state management when navigating between articles.
128-134
: LGTM!The path building logic correctly handles the URL structure with English as the default language (no prefix) and other languages with their respective prefixes.
libs/blog/shared/util-seo/src/lib/services/seo.service.ts (6)
16-19
: LGTM!The
HreflangEntry
interface is well-defined with the necessary properties for hreflang tag generation.
141-160
: LGTM!The
setHreflang
method correctly implements hreflang tag management:
- Properly clears existing tags before adding new ones
- Handles both absolute and relative URLs
- Correctly adds the
x-default
hreflang tag following SEO best practices
162-164
: LGTM!The
clearHreflang
method provides a clean public API for removing hreflang tags.
246-247
: LGTM!Correctly ensures that hreflang tags are removed along with other SEO metadata during cleanup.
249-268
: LGTM!The
handleAutoHreflang
method correctly generates hreflang entries for all available languages using the localization service.
270-283
: LGTM!The helper methods correctly handle DOM manipulation for hreflang tags:
appendHreflangLink
properly creates link elements with required attributesremoveHreflangTags
efficiently removes all existing hreflang tags using a specific selector
export function buildArticleHreflangEntries( | ||
article: Article, | ||
): HreflangEntry[] | null { | ||
if (!article.otherTranslations || article.otherTranslations.length < 2) { | ||
return null; | ||
} | ||
|
||
return article.otherTranslations.map((translation) => { | ||
const langCode = articleLocaleToLangMap[translation.locale]; | ||
const url = buildArticlePath(translation.slug, langCode); | ||
|
||
return { | ||
locale: langCode, | ||
url: url, | ||
} satisfies HreflangEntry; | ||
}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing current article language in hreflang entries
The hreflang implementation should include ALL language versions of the article, including the current one. Currently, it only maps otherTranslations
which excludes the current article's language.
Additionally, the length check seems incorrect. If otherTranslations
contains only other languages, you'd want hreflang entries even with 1 translation (current + 1 other = 2 languages total).
export function buildArticleHreflangEntries(
article: Article,
): HreflangEntry[] | null {
- if (!article.otherTranslations || article.otherTranslations.length < 2) {
+ if (!article.otherTranslations || article.otherTranslations.length === 0) {
return null;
}
- return article.otherTranslations.map((translation) => {
+ // Include current article
+ const allTranslations = [
+ { locale: article.language, slug: article.slug },
+ ...article.otherTranslations,
+ ];
+
+ return allTranslations.map((translation) => {
const langCode = articleLocaleToLangMap[translation.locale];
const url = buildArticlePath(translation.slug, langCode);
return {
locale: langCode,
url: url,
} satisfies HreflangEntry;
});
}
Note: You'll need to verify that article.language
type matches ArticleLocale
for the mapping to work correctly.
🤖 Prompt for AI Agents
In libs/blog/articles/data-access/src/lib/state/article-details.store.ts around
lines 110 to 126, the function buildArticleHreflangEntries only includes
otherTranslations and excludes the current article language, and the length
check incorrectly requires at least 2 other translations. Modify the function to
include the current article's language and URL in the hreflang entries along
with otherTranslations, and adjust the length check to allow hreflang entries
when there is at least one other translation. Also, verify that article.language
matches the expected locale type for the mapping to work correctly.
Summary by CodeRabbit