Skip to content

Commit 9ae3a11

Browse files
caugnerfiji-flo
andauthored
enhance(page): add other_translations to non-Doc pages (#272)
* refactor(translations): extract other_translations() * fix(spa): add other_translations * fix(translation): read SPA separately * chore(translations): move other_translations() * chore(translations): unpublish get_other_translations_for() It is no longer used anywhere else. * refactor(translations): pass doc through * chore(translations): use Page::from_url() * chore(translations): use current locale directly * fix(translations): check url for "/docs/" * chore(pages): simplify other_translations for conflicting/orphaned * chore(pages): inline other_translations where possible * chore(pages): inline parents where possible * refactor(translations): use Page::internal_from_url() * enhance(page): avoid unnecessary lookups * refactor(page): inverse if-else logic * chore(page): revert special Blog Index handling We don't currently need this yet, because we don't call `other_translations()` to determine the ones from the blog indices. * refactor(page): improve readability Co-authored-by: Florian Dieminger <[email protected]> --------- Co-authored-by: Florian Dieminger <[email protected]>
1 parent 9627c9b commit 9ae3a11

File tree

5 files changed

+84
-44
lines changed

5 files changed

+84
-44
lines changed

crates/rari-doc/src/pages/build.rs

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use scraper::Html;
1212
use super::json::{
1313
BuiltPage, Compat, ContributorSpotlightHyData, JsonBlogPostDoc, JsonBlogPostPage,
1414
JsonCurriculumPage, JsonDoc, JsonDocPage, JsonGenericHyData, JsonGenericPage, Prose, Section,
15-
Source, SpecificationSection, TocEntry, Translation,
15+
Source, SpecificationSection, TocEntry,
1616
};
1717
use super::page::{Page, PageBuilder, PageLike};
1818
use super::types::contributors::ContributorSpotlight;
@@ -30,7 +30,7 @@ use crate::html::sections::{split_sections, BuildSection, BuildSectionType, Spli
3030
use crate::html::sidebar::{
3131
build_sidebars, expand_details_and_mark_current_for_inline_sidebar, postprocess_sidebar,
3232
};
33-
use crate::pages::json::{CommonJsonData, JsonContributorSpotlightPage};
33+
use crate::pages::json::{CommonJsonData, JsonContributorSpotlightPage, Translation};
3434
use crate::pages::templates::{
3535
BlogRenderer, ContributorSpotlightRenderer, CurriculumRenderer, DocPageRenderer,
3636
GenericRenderer,
@@ -45,7 +45,7 @@ use crate::pages::types::spa::SPA;
4545
use crate::pages::types::utils::FmTempl;
4646
use crate::specs::extract_specifications;
4747
use crate::templ::render::{decode_ref, render, Rendered};
48-
use crate::translations::get_other_translations_for;
48+
use crate::translations::other_translations;
4949

5050
impl From<BuildSection<'_>> for Section {
5151
fn from(value: BuildSection) -> Self {
@@ -270,21 +270,20 @@ fn build_doc(doc: &Doc) -> Result<BuiltPage, DocError> {
270270
history.map(|entry| entry.hash.as_str()).unwrap_or_default()
271271
);
272272
let popularity = popularities().popularities.get(doc.url()).cloned();
273-
let other_translations = get_other_translations_for(doc.slug(), doc.locale())
274-
.into_iter()
275-
.map(|(locale, title)| Translation {
276-
native: locale.into(),
277-
locale,
278-
title,
279-
})
280-
.collect();
281-
282273
let no_indexing =
283274
doc.meta.slug == "MDN/Kitchensink" || doc.is_orphaned() || doc.is_conflicting();
284-
let parents = if !doc.is_conflicting() && !doc.is_orphaned() {
285-
parents(doc)
275+
276+
let (parents, other_translations) = if !doc.is_conflicting() && !doc.is_orphaned() {
277+
(parents(doc), other_translations(doc))
286278
} else {
287-
Default::default()
279+
(
280+
Default::default(),
281+
vec![Translation {
282+
native: doc.locale().into(),
283+
locale: doc.locale(),
284+
title: doc.title().to_string(),
285+
}],
286+
)
288287
};
289288

290289
Ok(BuiltPage::Doc(Box::new(JsonDocPage {
@@ -354,24 +353,28 @@ fn build_blog_post(post: &BlogPost) -> Result<BuiltPage, DocError> {
354353
locale: post.locale(),
355354
blog_meta: Some((&post.meta).into()),
356355
page_title: page_title(post, false)?,
357-
common: CommonJsonData {
358-
parents: parents(post),
359-
..Default::default()
360-
},
361356
image: Some(format!(
362357
"{}{}{}",
363358
base_url(),
364359
post.url(),
365360
post.meta.image.file
366361
)),
362+
common: CommonJsonData {
363+
parents: parents(post),
364+
other_translations: vec![Translation {
365+
native: post.locale().into(),
366+
locale: post.locale(),
367+
title: post.title().to_string(),
368+
}],
369+
..Default::default()
370+
},
367371
renderer: BlogRenderer::BlogPost,
368372
..Default::default()
369373
})))
370374
}
371375

372376
fn build_generic_page(page: &Generic) -> Result<BuiltPage, DocError> {
373377
let built = build_content(page);
374-
let parents = parents(page);
375378
let PageContent { body, toc, .. } = built?;
376379
Ok(BuiltPage::GenericPage(Box::new(JsonGenericPage {
377380
hy_data: JsonGenericHyData {
@@ -389,7 +392,8 @@ fn build_generic_page(page: &Generic) -> Result<BuiltPage, DocError> {
389392
id: page.meta.page.clone(),
390393
common: CommonJsonData {
391394
description: page.meta.description.clone(),
392-
parents,
395+
parents: parents(page),
396+
other_translations: other_translations(page),
393397
},
394398
renderer: match page.meta.template {
395399
super::types::generic::Template::GenericDoc => GenericRenderer::GenericDoc,
@@ -406,8 +410,7 @@ fn build_spa(spa: &SPA) -> Result<BuiltPage, DocError> {
406410
fn build_curriculum(curriculum: &Curriculum) -> Result<BuiltPage, DocError> {
407411
let PageContent { body, toc, .. } = build_content(curriculum)?;
408412
let sidebar = build_sidebar().ok();
409-
let parents = parents(curriculum);
410-
let group = curriculum_group(&parents);
413+
let group = curriculum_group(&parents(curriculum));
411414
let modules = match curriculum.meta.template {
412415
Template::Overview => build_overview_modules(curriculum.slug())?,
413416
Template::Landing => build_landing_modules()?,
@@ -424,7 +427,7 @@ fn build_curriculum(curriculum: &Curriculum) -> Result<BuiltPage, DocError> {
424427
locale: curriculum.locale(),
425428
native: curriculum.locale().into(),
426429
mdn_url: curriculum.meta.url.clone(),
427-
parents,
430+
parents: parents(curriculum),
428431
page_title: page_title(curriculum, true)?,
429432
summary: curriculum.meta.summary.clone(),
430433
body,
@@ -462,15 +465,15 @@ fn build_contributor_spotlight(cs: &ContributorSpotlight) -> Result<BuiltPage, D
462465
usernames: cs.meta.usernames.clone(),
463466
quote: cs.meta.quote.clone(),
464467
};
465-
let parents = parents(cs);
466468
Ok(BuiltPage::ContributorSpotlight(Box::new(
467469
JsonContributorSpotlightPage {
468470
url: cs.meta.url.clone(),
469471
page_title: cs.meta.title.clone(),
470472
hy_data: contributor_spotlight_data,
471473
common: CommonJsonData {
472474
description: cs.meta.description.clone(),
473-
parents,
475+
parents: parents(cs),
476+
other_translations: other_translations(cs),
474477
},
475478
renderer: ContributorSpotlightRenderer::ContributorSpotlight,
476479
},

crates/rari-doc/src/pages/json.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -961,10 +961,11 @@ pub struct JsonGenericPage {
961961
}
962962

963963
#[derive(Debug, Clone, Default, Serialize, JsonSchema)]
964-
#[serde(rename_all = "camelCase")]
965964
#[schemars(rename = "GenericPage")]
966965
pub struct CommonJsonData {
967966
pub description: Option<String>,
968967
#[serde(skip_serializing_if = "Vec::is_empty")]
969968
pub parents: Vec<Parent>,
969+
#[serde(skip_serializing_if = "Vec::is_empty")]
970+
pub other_translations: Vec<Translation>,
970971
}

crates/rari-doc/src/pages/page.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,24 @@ impl Page {
114114
.ok_or(DocError::PageNotFound(url.to_string(), PageCategory::SPA)),
115115
PageCategory::Doc => Doc::page_from_slug_path(&folder_path, locale, fallback)
116116
.map_err(|_| DocError::PageNotFound(url.to_string(), PageCategory::Doc)),
117+
PageCategory::BlogPost if locale != Locale::EnUs => {
118+
// Blog is en-US only.
119+
Err(DocError::PageNotFound(
120+
url.to_string(),
121+
PageCategory::BlogPost,
122+
))
123+
}
117124
PageCategory::BlogPost => BlogPost::page_from_url(url).ok_or(DocError::PageNotFound(
118125
url.to_string(),
119126
PageCategory::BlogPost,
120127
)),
128+
PageCategory::Curriculum if locale != Locale::EnUs => {
129+
// Curriculum is en-US only.
130+
Err(DocError::PageNotFound(
131+
url.to_string(),
132+
PageCategory::Curriculum,
133+
))
134+
}
121135
PageCategory::Curriculum => Curriculum::page_from_url(url).ok_or(
122136
DocError::PageNotFound(url.to_string(), PageCategory::Curriculum),
123137
),

crates/rari-doc/src/pages/types/spa.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,13 @@ use crate::helpers::parents::parents;
2222
use crate::helpers::title::page_title;
2323
use crate::pages::json::{
2424
BlogIndex, BuiltPage, CommonJsonData, ItemContainer, JsonBlogPostDoc, JsonBlogPostPage,
25-
JsonHomePage, JsonHomePageSPAHyData, JsonSpaPage, Parent,
25+
JsonHomePage, JsonHomePageSPAHyData, JsonSpaPage, Parent, Translation,
2626
};
2727
use crate::pages::page::{Page, PageLike, PageReader};
2828
use crate::pages::templates::{BlogRenderer, HomeRenderer, SpaBuildTemplate, SpaRenderer};
2929
use crate::pages::types::blog::BlogMeta;
3030
use crate::pages::types::utils::FmTempl;
31+
use crate::translations::other_translations;
3132

3233
#[derive(Debug, Clone)]
3334
pub struct SPA {
@@ -144,6 +145,11 @@ impl SPA {
144145
uri: "/en-US/blog/".to_string(),
145146
title: self.title().to_owned(),
146147
}],
148+
other_translations: vec![Translation {
149+
native: self.locale().into(),
150+
locale: self.locale(),
151+
title: self.title().to_string(),
152+
}],
147153
..Default::default()
148154
},
149155
image: None,
@@ -159,6 +165,7 @@ impl SPA {
159165
url: concat_strs!(self.base_slug.as_ref(), self.slug),
160166
common: CommonJsonData {
161167
parents: parents(self),
168+
other_translations: other_translations(self),
162169
..Default::default()
163170
},
164171
renderer: match self.template {
@@ -189,6 +196,7 @@ impl SPA {
189196
url: concat_strs!(self.base_slug.as_ref(), self.slug),
190197
common: CommonJsonData {
191198
parents: parents(self),
199+
other_translations: other_translations(self),
192200
..Default::default()
193201
},
194202
renderer: SpaRenderer::SpaNotFound,
@@ -212,6 +220,7 @@ impl SPA {
212220
},
213221
common: CommonJsonData {
214222
parents: parents(self),
223+
other_translations: other_translations(self),
215224
..Default::default()
216225
},
217226
renderer: HomeRenderer::Homepage,

crates/rari-doc/src/translations.rs

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use rari_types::globals::cache_content;
1010
use rari_types::locale::Locale;
1111

1212
use crate::cached_readers::{STATIC_DOC_PAGE_FILES, STATIC_DOC_PAGE_TRANSLATED_FILES};
13-
use crate::pages::page::PageLike;
14-
use crate::pages::types::doc::Doc;
13+
use crate::pages::json::Translation;
14+
use crate::pages::page::{Page, PageLike};
1515

1616
pub type TranslationsOf<'a> = BTreeMap<Locale, &'a str>;
1717

@@ -44,23 +44,32 @@ pub(crate) fn init_translations_from_static_docs() {
4444
TRANSLATIONS_BY_SLUG.set(all).unwrap();
4545
}
4646

47-
/// Retrieves translations for a specific slug, _excluding_ the specified locale.
48-
///
49-
/// This function looks up translations for the given slug in the global `TRANSLATIONS_BY_SLUG` cache.
50-
/// It filters out the translation for the specified locale and returns a vector of tuples containing
51-
/// the locale and the corresponding title for each translation.
47+
/// Determines all available translations for a specific page.
5248
///
5349
/// # Arguments
5450
///
55-
/// * `slug` - A string slice that holds the slug of the documentation page.
56-
/// * `locale` - A `Locale` that specifies the locale to be excluded from the results.
51+
/// * `doc` - The page for which the translations should be determined.
5752
///
5853
/// # Returns
5954
///
60-
/// * `Vec<(Locale, String)>` - Returns a vector of tuples, where each tuple contains a `Locale` and a `String`
61-
/// representing the title of the translation. If no translations are found, an empty vector is returned.
62-
pub(crate) fn get_other_translations_for(slug: &str, locale: Locale) -> Vec<(Locale, String)> {
63-
if cache_content() {
55+
/// * `Vec<Translation>` - The vector of translations (including the current locale).
56+
pub(crate) fn other_translations<T: PageLike>(doc: &T) -> Vec<Translation> {
57+
get_other_translations_for(doc)
58+
.into_iter()
59+
.map(|(locale, title)| Translation {
60+
native: locale.into(),
61+
locale,
62+
title,
63+
})
64+
.collect()
65+
}
66+
67+
fn get_other_translations_for<T: PageLike>(doc: &T) -> Vec<(Locale, String)> {
68+
let slug = doc.slug();
69+
let locale = doc.locale();
70+
let url = doc.url();
71+
72+
if cache_content() && url.contains("/docs/") {
6473
TRANSLATIONS_BY_SLUG
6574
.get()
6675
.and_then(|by_slug| {
@@ -82,9 +91,13 @@ pub(crate) fn get_other_translations_for(slug: &str, locale: Locale) -> Vec<(Loc
8291
Locale::for_generic_and_spas()
8392
.iter()
8493
.filter_map(|l| {
85-
Doc::page_from_slug(slug, *l, false)
86-
.ok()
87-
.map(|d| (*l, d.title().to_string()))
94+
if *l == locale {
95+
Some((*l, doc.title().to_string()))
96+
} else {
97+
Page::internal_from_url(url, Some(*l), false)
98+
.ok()
99+
.map(|d| (*l, d.title().to_string()))
100+
}
88101
})
89102
.collect()
90103
}

0 commit comments

Comments
 (0)