diff --git a/library/src/layout/table.rs b/library/src/layout/table.rs index 9ca6a137a..6e3e6330c 100644 --- a/library/src/layout/table.rs +++ b/library/src/layout/table.rs @@ -285,7 +285,7 @@ impl> From> for Value { } impl LocalName for TableElem { - fn local_name(&self, lang: Lang) -> &'static str { + fn local_name(&self, lang: Lang, _: Option) -> &'static str { match lang { Lang::ARABIC => "جدول", Lang::BOKMÅL => "Tabell", diff --git a/library/src/math/mod.rs b/library/src/math/mod.rs index 63bfdbbe0..47c28d179 100644 --- a/library/src/math/mod.rs +++ b/library/src/math/mod.rs @@ -277,7 +277,7 @@ impl Count for EquationElem { } impl LocalName for EquationElem { - fn local_name(&self, lang: Lang) -> &'static str { + fn local_name(&self, lang: Lang, _: Option) -> &'static str { match lang { Lang::ARABIC => "معادلة", Lang::BOKMÅL => "Ligning", @@ -305,10 +305,11 @@ impl Refable for EquationElem { vt: &mut Vt, supplement: Option, lang: Lang, + region: Option, ) -> SourceResult { // first we create the supplement of the heading let mut supplement = - supplement.unwrap_or_else(|| TextElem::packed(self.local_name(lang))); + supplement.unwrap_or_else(|| TextElem::packed(self.local_name(lang, region))); // we append a space if the supplement is not empty if !supplement.is_empty() { diff --git a/library/src/meta/bibliography.rs b/library/src/meta/bibliography.rs index 368a7c397..99f2111fe 100644 --- a/library/src/meta/bibliography.rs +++ b/library/src/meta/bibliography.rs @@ -152,10 +152,14 @@ impl Show for BibliographyElem { let mut seq = vec![]; if let Some(title) = self.title(styles) { - let title = title.unwrap_or_else(|| { - TextElem::packed(self.local_name(TextElem::lang_in(styles))) + let title = + title.unwrap_or_else(|| { + TextElem::packed(self.local_name( + TextElem::lang_in(styles), + TextElem::region_in(styles), + )) .spanned(self.span()) - }); + }); seq.push(HeadingElem::new(title).with_level(NonZeroUsize::ONE).pack()); } @@ -206,7 +210,7 @@ impl Finalize for BibliographyElem { } impl LocalName for BibliographyElem { - fn local_name(&self, lang: Lang) -> &'static str { + fn local_name(&self, lang: Lang, _: Option) -> &'static str { match lang { Lang::ARABIC => "المراجع", Lang::BOKMÅL => "Bibliografi", diff --git a/library/src/meta/figure.rs b/library/src/meta/figure.rs index d86625b75..bfbfeb833 100644 --- a/library/src/meta/figure.rs +++ b/library/src/meta/figure.rs @@ -193,7 +193,10 @@ impl Synthesize for FigureElem { Smart::Auto => match &kind { FigureKind::Elem(func) => { let elem = Content::new(*func).with::().map(|c| { - TextElem::packed(c.local_name(TextElem::lang_in(styles))) + TextElem::packed(c.local_name( + TextElem::lang_in(styles), + TextElem::region_in(styles), + )) }); if numbering.is_some() { @@ -273,6 +276,7 @@ impl Refable for FigureElem { vt: &mut Vt, supplement: Option, _: Lang, + _: Option, ) -> SourceResult { // If the figure is not numbered, we cannot reference it. // Otherwise we build the supplement and numbering scheme. @@ -283,7 +287,12 @@ impl Refable for FigureElem { Ok(desc) } - fn outline(&self, vt: &mut Vt, _: Lang) -> SourceResult> { + fn outline( + &self, + vt: &mut Vt, + _: Lang, + _: Option, + ) -> SourceResult> { // If the figure is not outlined, it is not referenced. if !self.outlined(StyleChain::default()) { return Ok(None); diff --git a/library/src/meta/heading.rs b/library/src/meta/heading.rs index ad8363634..43505448a 100644 --- a/library/src/meta/heading.rs +++ b/library/src/meta/heading.rs @@ -164,13 +164,14 @@ impl Refable for HeadingElem { vt: &mut Vt, supplement: Option, lang: Lang, + region: Option, ) -> SourceResult { // Create the supplement of the heading. let mut supplement = if let Some(supplement) = supplement { supplement } else { match self.supplement(StyleChain::default()) { - Smart::Auto => TextElem::packed(self.local_name(lang)), + Smart::Auto => TextElem::packed(self.local_name(lang, region)), Smart::Custom(None) => Content::empty(), Smart::Custom(Some(supplement)) => { supplement.resolve(vt, std::iter::once(Value::from(self.clone())))? @@ -208,7 +209,12 @@ impl Refable for HeadingElem { Counter::of(Self::func()) } - fn outline(&self, vt: &mut Vt, _: Lang) -> SourceResult> { + fn outline( + &self, + vt: &mut Vt, + _: Lang, + _: Option, + ) -> SourceResult> { // Check whether the heading is outlined. if !self.outlined(StyleChain::default()) { return Ok(None); @@ -228,7 +234,7 @@ impl Refable for HeadingElem { } impl LocalName for HeadingElem { - fn local_name(&self, lang: Lang) -> &'static str { + fn local_name(&self, lang: Lang, _: Option) -> &'static str { match lang { Lang::ARABIC => "الفصل", Lang::BOKMÅL => "Kapittel", diff --git a/library/src/meta/mod.rs b/library/src/meta/mod.rs index 5ec40e421..279fe54a1 100644 --- a/library/src/meta/mod.rs +++ b/library/src/meta/mod.rs @@ -27,9 +27,10 @@ pub use self::reference::*; pub use self::state::*; use typst::doc::Lang; +use typst::doc::Region; /// The named with which an element is referenced. pub trait LocalName { - /// Get the name in the given language. - fn local_name(&self, lang: Lang) -> &'static str; + /// Get the name in the given language and (optionally) region. + fn local_name(&self, lang: Lang, region: Option) -> &'static str; } diff --git a/library/src/meta/outline.rs b/library/src/meta/outline.rs index 252111644..8e1bb7233 100644 --- a/library/src/meta/outline.rs +++ b/library/src/meta/outline.rs @@ -1,5 +1,7 @@ use std::str::FromStr; +use typst::util::option_eq; + use super::{ Counter, CounterKey, HeadingElem, LocalName, Numbering, NumberingPattern, Refable, }; @@ -141,10 +143,14 @@ impl Show for OutlineElem { let mut seq = vec![ParbreakElem::new().pack()]; // Build the outline title. if let Some(title) = self.title(styles) { - let title = title.unwrap_or_else(|| { - TextElem::packed(self.local_name(TextElem::lang_in(styles))) + let title = + title.unwrap_or_else(|| { + TextElem::packed(self.local_name( + TextElem::lang_in(styles), + TextElem::region_in(styles), + )) .spanned(self.span()) - }); + }); seq.push(HeadingElem::new(title).with_level(NonZeroUsize::ONE).pack()); } @@ -152,6 +158,7 @@ impl Show for OutlineElem { let indent = self.indent(styles); let depth = self.depth(styles).map_or(usize::MAX, NonZeroUsize::get); let lang = TextElem::lang_in(styles); + let region = TextElem::region_in(styles); let mut ancestors: Vec<&Content> = vec![]; let elems = vt.introspector.query(&self.target(styles)); @@ -165,7 +172,7 @@ impl Show for OutlineElem { continue; } - let Some(outline) = refable.outline(vt, lang)? else { + let Some(outline) = refable.outline(vt, lang, region)? else { continue; }; @@ -255,10 +262,11 @@ impl Finalize for OutlineElem { } impl LocalName for OutlineElem { - fn local_name(&self, lang: Lang) -> &'static str { + fn local_name(&self, lang: Lang, region: Option) -> &'static str { match lang { Lang::ARABIC => "المحتويات", Lang::BOKMÅL => "Innhold", + Lang::CHINESE if option_eq(region, "TW") => "目錄", Lang::CHINESE => "目录", Lang::CZECH => "Obsah", Lang::FRENCH => "Table des matières", diff --git a/library/src/meta/reference.rs b/library/src/meta/reference.rs index adbc9f578..29b28828e 100644 --- a/library/src/meta/reference.rs +++ b/library/src/meta/reference.rs @@ -184,10 +184,11 @@ impl Show for RefElem { }; let lang = TextElem::lang_in(styles); + let region = TextElem::region_in(styles); let reference = elem .with::() .expect("element should be refable") - .reference(vt, supplement, lang)?; + .reference(vt, supplement, lang, region)?; Ok(reference.linked(Destination::Location(elem.location().unwrap()))) } @@ -259,21 +260,27 @@ pub trait Refable { /// /// # Arguments /// - `vt` - The virtual typesetter. - /// - `styles` - The styles of the reference. - /// - `location` - The location where the reference is being created. /// - `supplement` - The supplement of the reference. + /// - `lang`: The language of the reference. + /// - `region`: The region of the reference. fn reference( &self, vt: &mut Vt, supplement: Option, lang: Lang, + region: Option, ) -> SourceResult; /// Tries to build an outline element for this element. /// If this returns `None`, the outline will not include this element. /// By default this just calls [`Refable::reference`]. - fn outline(&self, vt: &mut Vt, lang: Lang) -> SourceResult> { - self.reference(vt, None, lang).map(Some) + fn outline( + &self, + vt: &mut Vt, + lang: Lang, + region: Option, + ) -> SourceResult> { + self.reference(vt, None, lang, region).map(Some) } /// Returns the level of this element. diff --git a/library/src/text/raw.rs b/library/src/text/raw.rs index 6cd1fc123..1c2164832 100644 --- a/library/src/text/raw.rs +++ b/library/src/text/raw.rs @@ -201,7 +201,7 @@ impl Finalize for RawElem { } impl LocalName for RawElem { - fn local_name(&self, lang: Lang) -> &'static str { + fn local_name(&self, lang: Lang, _: Option) -> &'static str { match lang { Lang::ARABIC => "قائمة", Lang::BOKMÅL => "Utskrift", diff --git a/library/src/visualize/image.rs b/library/src/visualize/image.rs index 3d51743a7..69eaa5bdc 100644 --- a/library/src/visualize/image.rs +++ b/library/src/visualize/image.rs @@ -122,7 +122,7 @@ impl Layout for ImageElem { } impl LocalName for ImageElem { - fn local_name(&self, lang: Lang) -> &'static str { + fn local_name(&self, lang: Lang, _: Option) -> &'static str { match lang { Lang::ARABIC => "شكل", Lang::BOKMÅL => "Figur", diff --git a/src/doc.rs b/src/doc.rs index b7b1eacdb..5f62506ae 100644 --- a/src/doc.rs +++ b/src/doc.rs @@ -591,6 +591,12 @@ impl Region { } } +impl PartialEq<&str> for Region { + fn eq(&self, other: &&str) -> bool { + self.as_str() == *other + } +} + impl FromStr for Region { type Err = &'static str; @@ -688,3 +694,23 @@ cast_to_value! { "y" => Value::Length(v.point.y.into()), }) } + +#[cfg(test)] +mod tests { + use crate::{doc::Region, util::option_eq}; + + #[test] + fn test_partialeq_str() { + let region = Region([b'U', b'S']); + assert_eq!(region, "US"); + assert_ne!(region, "AB"); + } + + #[test] + fn test_region_option_eq() { + let region = Some(Region([b'U', b'S'])); + + assert!(option_eq(region, "US")); + assert!(!option_eq(region, "AB")); + } +} diff --git a/src/util/mod.rs b/src/util/mod.rs index 592ba1fa2..83ec5961d 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -226,3 +226,13 @@ pub fn pretty_array_like(parts: &[impl AsRef], trailing_comma: bool) -> Str buf.push(')'); buf } + +/// Check if the [`Option`]-wrapped L is same to R. +/// +/// This is the stable version of [`Option::contains`]. +pub fn option_eq(left: Option, other: R) -> bool +where + L: PartialEq, +{ + left.map(|v| v == other).unwrap_or(false) +} diff --git a/tests/ref/text/lang-with-region.png b/tests/ref/text/lang-with-region.png new file mode 100644 index 000000000..097f105d3 Binary files /dev/null and b/tests/ref/text/lang-with-region.png differ diff --git a/tests/typ/text/lang-with-region.typ b/tests/typ/text/lang-with-region.typ new file mode 100644 index 000000000..344ca8d29 --- /dev/null +++ b/tests/typ/text/lang-with-region.typ @@ -0,0 +1,16 @@ +// Test if text with region works + +--- +// without any region +#set text(lang: "zh") +#outline() + +--- +// with unknown region configured +#set text(lang: "zh", region: "XX") +#outline() + +--- +// with region configured +#set text(lang: "zh", region: "TW") +#outline()